【问题标题】:How to write unit test with assertions in within the testet method?如何在 testet 方法中编写带有断言的单元测试?
【发布时间】:2012-03-23 13:27:34
【问题描述】:

我的问题是我喜欢测试一些在我的 junit 测试中被另一种方法隐藏的值。你怎么会这样。用 Mockito?子类化?

问题来了:

public class MyService extends AbstractService {

 public ResponseObject insert(SomeData data) {
     Request request = createRequest(data);
     Response response = new Response();
     callService(request, response);
     return createResponseObject(response);
 }

 protected void callBackendService(...) {
     ...
 }
}

您将如何测试传递给

的值
callBackendService()
方法?

有没有比使用子类化更优雅的方法?

 MyService service = new MyService() {

   @Override
   protected void callBackendService(...) {
      assertEquals(...);
      ...
   }
 }

问候,

迈克

【问题讨论】:

  • 测试callService。创建一个Response,调用该方法并进行测试。
  • callService() 应该是 callBackendService() 吗?

标签: java unit-testing junit4


【解决方案1】:

一种思想流派是,您应该只对您的公共课程进行单元测试。因此,只需对从 insert() 返回的 ResponseObject 进行断言即可。

否则,使用像 Mockito 这样的模拟框架,您可以将 callBackendService() 方法分解到它自己的类中(例如ServiceCaller)。然后您可以创建一个模拟 ServiceCaller 对象并验证传递给它的参数。

这样的……

public class ServiceCaller  {

    public callBackendService(Request request, Response response) {
        ...
    }

}

那么你的类应该看起来像这样......

public class MyService extends AbstractService {


    private ServiceCaller serviceCaller;

    public ResponseObject insert(SomeData data) {
     Request request = createRequest(data);
     Response response = new Response();
     serviceCaller.callBackendService(request, response);
     return createResponseObject(response);
    }

    public setServiceCaller(ServiceCaller caller) {
        this.serviceCaller = caller;        
    }

}

最后一个 Mockito 测试是这样的......

@Test
public void testInsert() throws Exception {

    // object to test
    MyService ms = new MyService();

    // test input values
    Request req = new Request();

    Response resp = new Response();

    // create a mock class and inject it into your test class
    ServiceCaller sc = mock(ServiceCaller.class);

    ms.setServiceCaller = sc;

    // execute the method under test
    ms.insert(req, resp);

    // now you can see if your mock was called with the expected params
    verify(sc).callBackendService(req, resp);
}

为了简洁,我省略了使用接口等的优秀设计,但你会明白的。

【讨论】:

    【解决方案2】:

    如果 callBackendService() 只是一个实现细节,请不要测试它。如果它非常复杂,值得自己测试,请将其重构为单独的类。

    【讨论】:

      【解决方案3】:

      注意:我假设 callService() 应该是 callBackendService()

      在您自己的一个类中,更多地关注测试行为而不是该类方法之间的交互。测试行为(与您尝试做的相反)将使您的测试无法与您的实现紧密耦合。例如,如果您继续尝试测试callBackendService() 方法,然后更改您的类的实现细节,您将破坏您的测试。相反,如果您专注于测试 insert() 方法的行为,您可以随时修改该特定调用,并且只有在您确实破坏了所需的行为时,您的测试才会中断。

      此外,让我们更详细地了解一下您的插入方法。如果您在其他测试中测试了createRequest() 方法和new Response() 构造函数的行为,那么您已经知道它们正在产生您期望的结果。因此,创建一个单独的测试来验证callBackendService() 方法收到了您在这种情况下所期望的参数,实际上并没有测试任何新内容。

      你应该做的是测试调用insert()方法的结果。

      所以你的问题的答案是,不要测试 callBackendService() 方法的参数。

      【讨论】:

        猜你喜欢
        • 2015-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-25
        • 1970-01-01
        • 2018-04-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多