alwaysAStudent
alwaysAStudent

Reputation: 2274

mock methods in same class

I am using Mockito to mock a method in the same class for which I am writing test. I have seen other answers on SO (Mocking method in the same class), but probably I am misunderstanding them, since I running into issues.

 class Temp() {

    public boolean methodA(String param) {

         try {

             if(methodB(param))
                   return true;

             return false;
         } catch (Exception e) {
               e.printStackTrace();
         }
    }
 }

My Test method:

 @Test
 public void testMethodA() {

    Temp temp = new Temp();
    Temp spyTemp = Mockito.spy(temp);

    Mockito.doReturn(true).when(spyTemp).methodB(Mockito.any()); 
    boolean status = temp.methodA("XYZ");

    Assert.assertEquals(true, status);
 }

I however get the expection printed out because definition of methodB gets executed. My understanding is definition of methodB would get mocked by using spyTemp. However that does not appear to be the case.

Can someone please explain where I am going wrong?

Upvotes: 64

Views: 133271

Answers (3)

Konstantin Labun
Konstantin Labun

Reputation: 3918

The first issue is that you have to use spyTemp object to expect something from Mockito. Here it is not the same as test. spyTemp is wrapped by the Mockito object temp.

Another issue is that you stub only methodB(), but you are trying to run methodA(). Yes in your implementation of methodA() you call methodB(), but you call this.methodB(), not spyTemp.methodB(). Here you have to understand that mocking would work only when you call it on the instance of temp. It's wrapped by a Mockito proxy which catches your call, and if you have overriden some method, it will call your new implementation instead of the original one. But since the original method is called, inside it you know nothing about Mockito proxy. So your "overriden" method would be called only when you run spyTemp.methodB()

This should work:

Mockito.doReturn(true).when(spyTemp).methodB(Mockito.any()); 
boolean status = spyTemp.methodA("XYZ");

Upvotes: 67

sprinter
sprinter

Reputation: 27986

Note the following from Mockito documentation:

Mockito does not delegate calls to the passed real instance, instead it actually creates a copy of it. So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction and their effect on real instance state. The corollary is that when an unstubbed method is called on the spy but not on the real instance, you won't see any effects on the real instance.

This is referring specifically to your situation. You keep a reference to temp and then call its methodA. Mockito is not spying on that instance at all; it's spying on spyTemp. So the normal methodB is called.

Note that you should avoid partial mocks altogether for new code.

Upvotes: 9

CoronA
CoronA

Reputation: 8095

You created a spy and mocked methodB(). That is correct! But you called methodA() on the original object. To get the correct result call it on the spy

boolean status = spyTemp.methodA("XYZ");

Upvotes: 26

Related Questions