Mocking a call to a public method of an abstract class without subclassing the abstract class using mockito is preferable

I am writing 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 make fun of the call abstract Class "SomeAbstractClass"mentioned in the previous code snippet so that I can test the call on "obj", for example:

verify(SomeAbstractClass).someMethod();
verify(obj).someOtherMethod();

I tried using mockito functions such as: Mockito.CALLS_REAL_METHODS Mockito.RETURNS_MOCKS

but they do not work due to dependencies not available to SomeAbstractClass.

Note:

1) SomeObject is an interface.

2) I need a technique for testing a piece of code. I am forced to use the above code fragment and cannot change the code fragment.

+5
4

: unit test, , - .

:

  • :
public someObject methodUnderTest() {
    SomeObject obj = getSomeObject();

    if(obj!=null){
      obj.someOtherMethod();
    }

    return someThing;
}

protected SomeObject getSomeObject() {
    return SomeAbstractClass.someMethod();
}
  • Mockito Spy , :
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);
}
+1
+2

, , CALLS_REAL_METHODS , (.. " " ). : thenCallRealMethod, - CALLS_REAL_METHODS, :

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 warned that SomeAbstractClass is never actually created, so if you rely on any behavior in the constructor of an abstract class, such as initializing variables - including inline initialization where fields are declared - you will need to make these calls explicitly yourself.

+2
source

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
}
+1
source

All Articles