0

I am trying to stub method of testing class. And it is not working.

Like am testing below class

enter code here
    Class to test:
    public Class A{
        public String method1(){
          C c=new C();
          int num=c.methodC();
          B b=new B();
          String str=method2(b);
          return str;
        }
   public String method2(B b){
         
          String str=method2(b);
          return str;
        }
    }


JUnit class:

    @RunWith(JUnitPlatform.class)
      Class ATest {

      @InjectMocks
      A a;
    
      @Mock
      C c;
      @Mock
      A a1;

      @BeforeEach 
      public void initMocks() {
        MockitoAnnotations.initMocks(this);
      }
    
      @Test
      public void testMethod1(){

        Mockito.doReturn(34).when(c).methodC(anyString());
        a1=Mockito.mock(A.class);
        Mockito.doReturn("Added successfully").when(a1).method2(any(B.class));
        assertEquals("Added successfully", a.method1());
      }
    }

When am stubbing methodC(...) from Class C it is working. But method2(...) from Class A is not stubbing.

Please let me know what is the issue, and solution.

  • you don't pass the mocks to object under test. you create new B and new C in method under test. On top of that there are a few typos: A1 is probably meant to be an instance of B. Mockito.mock is not necessary when calling initMocks – Lesiak Apr 09 '21 at 17:51
  • Edited my post, in either case : whether use Mockito.mock or not, irrespective of that actual methods are being called, not stubbing one. This happens when I call methods of same testing class. – Santoshalakshmi M Apr 12 '21 at 06:10
  • You still: 1. create new c in method under test and call a method on it. thus, stub of `c. methodC` does not work. 2. You stub `a1. method2` but call `a.method2`. a1 and a are 2 different objects, this stubbing also does not work. If you want to stub out only certain parts of an object, you need a @Spy, not a mock. – Lesiak Apr 12 '21 at 06:49
  • I initially used a.method2(..), to it didnt work, so tried with new object, thinking may be @InjectMock not allowing to stub the method. In both cases it is not calling stubbing method instead calls actual method. And I get : – Santoshalakshmi M Apr 12 '21 at 11:28
  • And I get exception as below, if I use same object for stubbing and invoking method for testing : Argument passed to when() is not a mock! – Santoshalakshmi M Apr 12 '21 at 11:40

2 Answers2

0

You have 2 options to mocka parts of the object.

Option 1: use a @Spy instead of a @Mock

@ExtendWith(MockitoExtension.class)
class ATest {

    @Spy
    A a;

    @Test
    public void testMethod1() {
        Mockito.doReturn("Added successfully").when(a).method2(any(B.class));
        assertEquals("Added successfully", a.method1());
    }
}

Option 2: Use a mock and mark real implementations

@ExtendWith(MockitoExtension.class)
class ATest {

    @Mock
    A a;

    @Test
    public void testMethod1() {
        Mockito.doReturn("Added successfully").when(a).method2(any(B.class));
        Mockito.doCallRealMethod().when(a).method1();
        assertEquals("Added successfully", a.method1());
    }
}
Lesiak
  • 22,088
  • 2
  • 41
  • 65
0

I found via trial and error method that, methods in testing class cannot be mocked. In case we have to mock a method, either we have to move such methods to different class, or do not mock it. That is the only solution.