与多个合作者进行单元测试

时间:2009-07-13 22:38:33

标签: java unit-testing http tdd apache-commons

今天我遇到了一个非常困难的TDD问题。我需要通过HTTP POST与服务器进行交互。我找到了Apache Commons HttpClient,它可以满足我的需要。

但是,我最终得到了来自Apache Commons的一堆协作对象:

public void postMessage(String url, String message) throws Exception {

    PostMethod post = new PostMethod(url);
    RequestEntity entity = new StringRequestEntity(message, 
                                      "text/xml; charset=ISO-8859-1");
    post.setRequestEntity(entity);
    HttpClient httpclient = new HttpClient();
    try {
        int result = httpclient.executeMethod(post);

        System.out.println("Response status code: " + result);
        System.out.println("Response body: ");
        System.out.println(post.getResponseBodyAsString());
    } finally {
        post.releaseConnection();
    }
}

我有一个PostMethod对象,一个RequestEntity对象和一个HttpClient对象。传递HttpClient ala依赖注入感觉相对舒服,但我该如何处理其他协作者呢?

我可以创建一堆工厂方法(或工厂类)来创建协作者,但我有点害怕我会嘲笑太多。

跟进

感谢您的回答!我剩下的问题是这样的方法:

public String postMessage(String url, String message) throws Exception {

    PostMethod post = new PostMethod(url);
    RequestEntity entity = new StringRequestEntity(message, 
                                      "text/xml; charset=ISO-8859-1");
    post.setRequestEntity(entity);
    HttpClient httpclient = new HttpClient();
    httpclient.executeMethod(post);
    return post.getResponseBodyAsString();
}

如何正确验证返回的值是否来自post.getResponseBodyAsString()?我是否必须模仿post以及client

2 个答案:

答案 0 :(得分:4)

简短回答:模拟HttpClient,不要模拟PostMethod或RequestEntity。

当然这是一个判断调用,但我建议从嘲笑真正需要嘲笑的事情开始:HttpClient。 PostMethod和RequestEntity是堆栈本地的,快速的和确定性的,我会保留它们,如果有必要,你可以随后嘲笑它们。正如您的代码现在一样,通过模拟PostMethod和RequestEntity,您会使api复杂化,使用api的代码变得复杂,并公开实现的详细信息。
随着您的代码的发展,您将更好地了解需要嘲笑的内容,无需尝试预测未来。

这可能有用:

http://www.testingreflections.com/node/view/7417

答案 1 :(得分:3)

zielaj的回答是合理的,但你也可以使用以下签名创建一个PostMethodFactory:

PostMethod getInstance(String url, String message, String contentType);

...然后使用DI注入它和HttpClient。那么你只有两件事要嘲笑。

PostMethodFactory可以这样实现:

public PostMethod getInstance(String url, String content, String contentType, String charset) {
  PostMethod post = new PostMethod(url);
  RequestEntity entity = new StringRequestEntity(message, contentType, charset);
  post.setRequestEntity(entity);
  return post;
}