public void doFoo(int x, int y, String url) {
    JSONObject json = new JSONObject().put("z", x + y);
     try (final HttpUtility httpUtils = new HttpUtility()) {
          httpUtils.doAuthPutJson(url,json);
      }
}


我想验证对HTTPUtlity的输入。我该如何编写单元测试?

最佳答案

实际上,当前类和HttpUtility在该方法中紧密耦合。
如果您认为HttpUtility是您希望能够模拟的依赖项,则必须以允许设置依赖项的方式使用它。

但是由于实际上您无法自然地在当前类中设置HttpUtility依赖关系,因此您认为PowerMockito将解决您的问题。
但实际上不会。
它只会隐藏设计问题。

只需稍作更改,您就可以以自然而直接的方式进行更清晰的设计和模拟HTTPUtlity实例化。

为了实现它,我将提取HttpUtility实例化为依赖项所执行的处理。

我可以这样获得代码:

public class Foo{

   private Supplier<HttpUtility> httpUtilitySupplier;

   public Foo(Supplier<HttpUtility> httpUtilitySupplier){
      this.httpUtilitySupplier = httpUtilitySupplier;
   }

   public void doFoo(int x, int y, String url) {
     JSONObject json = new JSONObject().put("z", x + y);
     try (final HttpUtility httpUtils = httpUtilitySupplier.get()) {
          httpUtils.doAuthPutJson(url,json);
      }
   }
}


请注意,我使用构造函数来设置依赖项,因为它允许为其设置不变量,但如果需要,也可以使用setter。

现在,您可以轻松地检查HttpUtility.doAuthPutJson()是否已通过测试中的预期参数调用:

@RunWith(MockitoJUnitRunner.class)
public class FooTest {

    @Mock
    private HttpUtility httpUtilityMock;

    @Test
    public void testName() throws Exception {
        // fixture
        Foo foo = new Foo( () -> httpUtilityMock);
        int x = ...;
        int y = ...;
        String url = ...;

        // action
        foo.doFoo(x, y, url);

        // assertion
        JSONObject expectedJSONObject = ...;
        Mockito.verify(httpUtilityMock).doAuthPutJson(url, expectedJSONObject);
    }
}

07-27 13:29