在间谍对象上使用验证

时间:2018-07-19 15:30:14

标签: java unit-testing mockito

我定义了一个间谍bean:

@Bean
public IMyService myServiceSpy()
{
    return Mockito.spy(new MyServiceImpl());
}

在测试中,我想捕获服务获得的参数。 当然,如果我将服务定义为模拟而不是间谍,则可以使用,但是我想激活服务的真实方法并继续执行流程,因为我需要由它计算返回值。

    @Inject
    private IMyService myServiceSpy;

    @Test
    public void myTest()
    {

    //act   
    //here invoking some service that will eventually invoke MyServiceImpl.

    //assert
    ArgumentCaptor<SomeObj> someObjCaptor = ArgumentCaptor.forClass(SomeObj.class);

    try
    {               
       Mockito.verify(myServiceSpy, Mockito.atLeastOnce()).create(someObjCaptor.capture());                 
    }
    catch(Exception e)
    {
        Assert.fail();
    }   
   assertEquals("some value" , someObjCaptor.getValue());

奇怪的是,当调用verify()时,间谍的方法再次被激活,但是这次使用NULL参数调用了该方法。

之后,它在声明上失败

org.mockito.exceptions.base.MockitoException:  No argument value was captured! You might have forgotten to use argument.capture() in verify()... ...or you used capture() in stubbing but stubbed method was not called. Be aware that it is recommended to use capture() only with verify()

Examples of correct argument capturing:
    ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
    verify(mock).doSomething(argument.capture());
    assertEquals("John", argument.getValue().getName());

我正在使用以下代码进行测试:

@RunWith(SpringJUnit4ClassRunner.class)

2 个答案:

答案 0 :(得分:0)

我不确定您是否应该使用@Inject来监视您的服务。

过去,这对我来说效果很好:

import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Spy;

import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.atLeastOnce;

...

@Spy
private MyServiceImpl myServiceSpy;

@Captor
private ArgumentCaptor<SomeObj> someObjCaptor;

@Test
public void myTest()
{

    ...

    try
    {               
       verify(myServiceSpy, atLeastOnce()).create(someObjCaptor.capture());

       SomeObj someObj = someObjCaptor.get();

       // Assert anything
    }
    catch(Exception e)
    {
        Assert.fail();
    }   

    ...

}

@Bean
public MyServiceImpl myServiceImpl()
{
    return new MyServiceImpl();
}

注释确实简化了代码。一旦您习惯了它们,就可以更轻松地阅读代码并在=)中键入代码

答案 1 :(得分:0)

问题是由于我在本文中发现的Spring AOP:

https://lkrnac.net/blog/2015/12/mock-spring-bean-v2/

我通过创建将调用原始bean的新类解决了该问题。 新类将在@Configuration类中侦听。

public class MyServiceImplSpy implements IMyServiceImpl
{

    @Inject
    @Qualifier("myServiceImpl")  
    private IMyService myService;  //the original bean          

    public String create(SomeObj someObj)
    {
        return myService.create(someObj);
    }

}
相关问题