【问题标题】:Easymock - nested void method testing (spying)Easymock - 嵌套 void 方法测试(间谍)
【发布时间】:2011-12-22 08:01:04
【问题描述】:

如何在 getData() 模拟测试期间在嵌套方法中监视参数“param”? Easymock 3 可以吗?

源代码

public class ServiceLogic {

 public void getData(){

  // some business logic

  serviceDAO.executeStatement(param);   

 }

}

Easymock 测试:

ServiceLogic _serviceLogicMock = EasyMock.createNiceMock(ServiceLogic.class);
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);

_serviceLogicMock.setServiceDAO(_serviceDAOMock);

//some other method calls -> .execute(...).andReturn(...);
EasyMock.replay(_serviceLogicMock);

//run
_serviceLogicMock.getData();

如何使用 EasyMock 检查 executeStatement() 方法是否以正确的参数调用?!

【问题讨论】:

  • 间谍是什么意思?您可以期待 serviceDAO.executeStatement 并为参数提供约束。
  • 参数设置在哪里?您可以将它传递给构造函数中的 ServiceLogic 吗?还是有二传手?如果有你可以使用when和verify。

标签: java junit4 mockito easymock


【解决方案1】:

你的测试似乎错了:

  • 你的单元测试是关于测试ServiceLogic那你为什么要模拟它?
  • 此外,您对与 ServiceDAO 模拟的任何交互都没有任何期望。

由于问题被标记为 Mockito,我建议您可以适应您的代码的以下解决方案(减去导入):

@RunWith(MockitoJUnitRunner.class)
public class ServiceLogicTest {
    @Mock ServiceDAO serviceDAO;
    @InjectMocks ServiceLogic serviceLogic;

    @Test
    public void ensure_executeStatement_is_called_with_right_param() throws Exception {
        // given
        String input = "Some input";

        // when
        serviceLogic.getDataFrom(input);

        // then
        verify(serviceDAO).executeStatement("expected param");
    }
}

在编写测试时,我喜欢使用 BDD(行为驱动开发)风格来指导我想要测试的内容。我鼓励你练习它,你可以看看wiki page

所以对于你的问题,你应该看看verify 行,它把模拟置于验证模式,所以实际上可以验证方法executeStatement 确实是用参数值"expected param" 调用的。

如果你有更复杂的参数,你可以使用一些匹配器,使用Hamcrestlibrary

verify(serviceDAO).executeStatement(argThat(hasProperty("propertyName")));

或者您可以将 Mockito 的 ArgumentCaptorFEST-Assert library 结合使用(通常是我的首选方法):

ArgumentCaptor<ComplexArgument> argCaptor = ArgumentCaptor.forClass(ComplexArgument.class);
verify(serviceDAO).executeStatement(argCaptor.capture());
assertThat(argCaptor.getValue()).isNotNull().satisfies(myComplexArgumentCondition());

主要思想是在生产代码中在测试代码中使用understandable code

如需进一步阅读,请查看Mockito Javadoc

【讨论】:

  • +1 用于介绍 FEST-Assert 库。 Hamcrest 的非常有趣的替代品(我喜欢并且目前正在使用)。
【解决方案2】:

与 @Brice 一样,我更喜欢 Mockito 而不是 EasyMock,但这里的 EasyMock 版本更接近您的原始示例,因为您的示例是 EasyMock。

public class ServiceLogicTest {

    @Test
    public void ensure_executeStatement_is_called_with_right_param() throws Exception {
        ServiceLogic _serviceLogicUT = new ServiceLogic();
        ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);

        _serviceLogicUT.setServiceDAO(_serviceDAOMock);

        String input = "Some input";

        //some other method calls -> .execute(...).andReturn(...);
        _serviceDaoMock.executeStatement("expected para");  // assuming a void method
        EasyMock.replay(_serviceDaoMock);            
        // run
        _serviceLogicUT.getDataFrom(input);

        // verifies that the expected calls were made
        EasyMock.verify(_serviceDaoMock);  
    }
}

EasyMock 还具有参数捕获功能。看起来像这样:

public class ServiceLogicTest {

    @Test
    public void ensure_executeStatement_is_called_with_right_param() throws Exception {
        ServiceLogic _serviceLogicUT = new ServiceLogic();
        ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);

        _serviceLogicUT.setServiceDAO(_serviceDAOMock);

        String input = "Some input";

        //some other method calls -> .execute(...).andReturn(...);
        Capture<ComplexParam> capturedParam = new Capture<ComplexParam>();
        _serviceDaoMock.executeStatement(EasyMock.capture(capturedParam));  // assuming a void method
        EasyMock.replay(_serviceDaoMock);            
        // run
        _serviceLogicUT.getDataFrom(input);

        ComplexParam actualParam = capturedParam.getValue();

        // make various assertions on actual param
    }
}

我想你可以从这两个例子中看出为什么很多人喜欢 Mockito,但如果你有一些理由喜欢或被要求使用 EasyMock,你可以用 Mockito 做任何你能做的事情,只需要更多的代码行.

【讨论】:

    【解决方案3】:

    这应该可以通过 jmockit 实现,除非您的 DAO 具有最终方法。但是,使用 jMockit 可以更好、更轻松地做到这一点:

    @Test
    public void testMethod(@Mocked final ServiceDAO serviceDAO) {
           new Expectations() {{
                serviceDAO.executeStatement(expectedOParams);returns(expectedReturnValue)
           }};
    
         (new ServiceLogic(serviceDAO)).getData();
    }
    

    这几乎是完整的测试保存断言。它适用于 final、static、abstract 和任何方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-27
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 2023-03-06
      • 1970-01-01
      相关资源
      最近更新 更多