I am writing an unit testing using JUNIT + Mockito to test a method like :
public someObject methodUnderTest(){
SomeObject obj = SomeAbstractClass.someMethod();
if(obj!=null){
obj.someOtherMethod();
}
return someThing;
}
And I would like to mock the call on abstract Class "SomeAbstractClass"
mentioned in above code fragment so i can verify call on "obj" like :
verify(SomeAbstractClass).someMethod();
verify(obj).someOtherMethod();
I have tried using mockito features like : Mockito.CALLS_REAL_METHODS Mockito.RETURNS_MOCKS
but they don't work due to dependencies not available to the SomeAbstractClass.
Note:
1) SomeObject is an Interface.
2) I need a technique to test above code fragment. I am constrained to use the above code fragment and cannot change the code fragment.
Spying abstract class using Mockito. spy() method is used to create a spy instance of the abstract class. Step 1: Create an abstract class named Abstract1_class that contains both abstract and non-abstract methods. Step 2: Create a JUnit test case named Abstract1Test. It contains a spy instance of the abstract class.
Then you can use the @Mock , @InjectMocks as you would normally. If you have an implemented class which extends the Abstract class, then just use that one to test the methods from the abstract class.
With JUnit, you can write a test class for any source class in your Java project. Even abstract classes, which, as you know, can't be instantiated, but may have constructors for the benefit of “concrete” subclasses.
Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.
You can use PowerMock to mock static and final methods.
It sounds like the problem is that your use of CALLS_REAL_METHODS is applying to the entire class, where you really want to mock out specific methods (i.e. make a "partial mock"). You have two options here, one using thenCallRealMethod
, and one using CALLS_REAL_METHODS
and then specifically mocking the calls you need:
public void testMethodUnderTest_mockSpecificThings() {
SomeAbstractClass myAbstractClass = Mockito.mock(SomeAbstractClass.class);
SomeAbstractClass myObject = Mockito.mock(SomeObject.class);
when(myAbstractClass.someMethod()).thenReturn(foo);
when(myAbstractClass.methodUnderTest()).thenCallRealMethod();
myAbstractClass.methodUnderTest();
verify(myAbstractClass).someMethod();
verify(myObject).someOtherMethod();
}
public void testMethodUnderTest_makeSpecificRealCalls() {
SomeAbstractClass myAbstractClass =
Mockito.mock(SomeAbstractClass.class, CALLS_REAL_METHODS);
SomeAbstractClass myObject = Mockito.mock(SomeObject.class);
// overrides the default answer
when(myAbstractClass.someMethod()).thenReturn(myObject);
myAbstractClass.methodUnderTest();
verify(myAbstractClass).someMethod();
verify(myObject).someOtherMethod();
}
Be forewarned that SomeAbstractClass is never actually instantiated, so if you rely on any behavior in the abstract class constructor, like variable initialization--including inline initialization where the fields are declared--you will need to make those calls explicitly yourself.
Assumption: if you write unit test, I guess you still can modify tested method a bit.
Solution:
public someObject methodUnderTest() { SomeObject obj = getSomeObject(); if(obj!=null){ obj.someOtherMethod(); } return someThing; } protected SomeObject getSomeObject() { return SomeAbstractClass.someMethod(); }
private ClassUnderTest classUnderTest; @Before public void setUp() { classUnderTest= new ClassUnderTest(); classUnderTest = Mockito.spy(classUnderTest); } @Test public void test() { SomeObject someObject = Mockito.mock(SomeObject.class); when(classUnderTest.getSomeObject()).thenReturn(someObject); classUnderTest.methodUnderTest(); verify(someObject).someOtherMethod(); } @Test public void testNull() { when(classUnderTest.getSomeObject()).thenReturn(null); classUnderTest.methodUnderTest(); verify(something); }
Use anonymous classes:
public interface SomeObject {
public Object someOtherMethod();
}
public abstract class SomeAbstractClass {
abstract SomeObject someMethod();
}
@Test
public void test() {
SomeAbstractClass target = new SomeAbstractClass() {
SomeObject someMethod() {
// some impl
SomeObject someObject = new SomeObject() {
public Object someOtherMethod() {
// some other impl
}
};
return someObject;
}
};
// now test target
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With