Unable to test with mockito for inheritance method

68 views Asked by At

I have the below code

class A {
    public int someMethod(int someParameters....) {
        ........// some implementation 
    }
}

class B extends A {
    public int someMethodFromB(int someParameters....) {
        ........// some implementation 
        return someMethod(someParameters....);
    }
}

I am writing test for class B for someMethodFromB and I want to mock someMethod which we are returning the value. How can I test the code as B is extending A.

I have tried the below 2 approaches but did not work out

@Test
public void testSomeMethodFromB() throws Exception {
      ContextData contextData = mock(ContextData.class);

      SomeObject obj = mock(SomeObject.class);

      B b = spy(new B());

      doReturn(obj).when(b).someMethod(obj, contextData, false);

      Assert.assertNotNull(b.someMethodFromB(someAnotherObj, contextData, Optional.of("someString")));

    }

and this one too

@Mock
private A a;

@InjectMock
private B b;

@Before
public void setUp() {
   MockitoAnnotations.initMocks(this);
}

@Test
public void testSomeMethodFromB() throws Exception {
     ContextData contextData = mock(ContextData.class);

     SomeObject obj = mock(SomeObject.class);

     when(a.someMethod(obj, contextData, false)).thenReturn(obj);

     b.someMethodFromB(someAnotherObj, contextData, Optional.of("someString"));

    }
2

There are 2 answers

0
NapoleonDynamite On

might be me but this:

@Test
public void testSomeMethodFromB() throws Exception {
     ContextData contextData = mock(ContextData.class);

     SomeObject obj = mock(SomeObject.class);

     when(a.someMethod(obj, contextData, false)).thenReturn(obj);

     b.someMethodFromB(someAnotherObj, contextData, Optional.of("someString"));

    }

makes no sense to me, what are SomeObject.class and SomeAnotherObj? SomeAnotherObj gets passed as a parameter but is never defined? You mock SomeObject.class but never mention it, is it just something you need for test, unrelated to the question? I think you could do something like this:

public class BTest {

    @Mock
    private A a;
    @InjectMocks
    private B b; 

    @Test
    public void testSomeMethodFromB() {

        when(a.someMethod(something)).thenReturn(something);


        int result = b.someMethodFromB(something);

        Assert.assertEquals(expected, result);
    }

again, maybe im mistaken, its been a long day at work, but i dont quite understand the examples Good luck anyhow!

0
Dyjah On

I tried a simplified version of what you are trying to do and it worked:

public class A {

    public int someMethod(int value) {
        return 2 * value;
    }
}
class B extends A {
  public int someMethodFromB(int value) {
    return someMethod(value);
  }
}
class BTest {

  @Test
   void myTest() {
     B spyB = spy(new B());
    
     doReturn(5).when(spyB).someMethod(8);

     assertEquals(5, spyB.someMethodFromB(8));
  }
}

So my guess is that the parameters that you are passing to someMethod in the test are not exactly the same the code is receiving when calling it.

For example if I change the parameter of someMethod to 6, the test fails, because when the code runs it receives the value 8 and not 6, so the spy does not apply:

  @Test
   void myTest() {
    B spyB = Mockito.spy(new B());

    Mockito.doReturn(5).when(spyB).someMethod(6);

    assertEquals(5, spyB.someMethodFromB(8));
  }

Debug your test and check what are the parameters when someMethod will be called to make sure they are the ones you are passing in the test at the doReturn... call.