简体   繁体   中英

Mockito Spy Test

I am using Mockito to write tests for code. However I am stuck at following scenario - Class A has 2 methods, method1() and method2(). I tried using ArgumentCaptor to catch values sent to method2(). But, since I am using @Spy, I cannot use Matchers.

How do I test method1()?

class A{
    B b;
    method1(arg1, arg2){
       //some logic
       method2(arg1, arg2, ....argN);
    }

   method2(arg1, arg2,....argN){
       //some logic
       b.method3(arg1, arg2...);
   }
}

How to verify method2 receives same argument values? Following is the test class I wrote:

Class TestA{

@Mock
B b;

@Spy
@InjectMocks   //required else b is null
A a = new A();

@Test
public void testMethod1(){

 a.method1(arg1, arg2);

  //How to verify method2 receives same argument values (arg1, arg2)????
  //verify(a, times(1)).method2(.......);   
}

}

I was intrigued by this post and the comments left by @David so I decided to code a working example for those who follow like me

/*
 * class to test
 */
public class A {

    public void methodA(String str) {
        this.methodB(str);
    }

    protected void methodB(String str) {
        // some implementation
    }
}

We want to assert that the value being passed into methodB() is what we expect. Reading up on the ArgumentCaptor led me to discover the equivalent Captor Annotation

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.verify;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class MultipleMethodCallTest {

    @Spy
    A a = new A();

    @Captor ArgumentCaptor<String> captor;

    @Test
    public void captureSecondMethodCallArgument() throws Exception {

        // EXPECTED

        String greeting = "hello world";

        // PERFORM TEST

        a.methodA(greeting);

        // ASSERT

        verify(a).methodB(captor.capture());

        assertEquals(greeting, captor.getValue());
    }
}

This example was tested with

  • mockito-all-1.8.5.jar
  • junit-4.8.2.jar

You cant, you have to verify it by B's method3 call. If your args to method2 have no effect on method3, theses args could be useless at all?!

You can use matchers with spies; this works just fine. I don't know why you thought that you couldn't.

I took your source code and edited it to make it compile. I then added a call to MockitoAnnotations.initMocks - you need this to create the spy and the mock, and to inject the mock (unless you use the MockitoJUnitRunner , which does the initMocks for you). I put the verify of the call to method2 back in. This worked fine.

So, contrary to Omnaest's answer, you don't need to use B's method3 to verify this. I suspect that your only problem was that you had forgotten the initMocks .

Good luck with this, and feel free to post again if you need any more help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM