有时候,当您正在对远程服务器进行HTTP调用的单元测试代码时。 您可能正在使用诸如Apache'sHttpClient或Spring的RestTemplate之类的库。
当然,您不想依靠远程服务进行单元测试。 除了涉及的开销(记住单元测试应该是快速的)之外,您根本不能依赖于在执行测试期间可以使用的远程服务。 您可能还无法完全控制所有测试方案的响应。
考虑下面的简化示例。
ExampleHttpCall
public class ExampleHttpCall {
private String serviceUrl;
public ExampleHttpCall(String url) {
serviceUrl = url;
}
public String doGet() {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.getForEntity(serviceUrl, String.class);
String response = responseEntity.getBody();
return response;
}
}
您将如何为ExampleHttpCall编写单元测试?
当然,您可以以这样的方式重新设计类,以使RestTemplate的实例被注入到类中:
ExampleHttpCall备用版本
@Component
public class ExampleHttpCallAlternateVersion {
@Resource
private RestTemplate restTemplate;
private String serviceUrl;
public ExampleHttpCallAlternateVersion(String url) {
serviceUrl = url;
}
public String doGet() {
ResponseEntity<String> responseEntity = restTemplate.getForEntity(serviceUrl, String.class);
String response = responseEntity.getBody();
return response;
}
}
现在可以嘲笑该依赖关系,从而使您可以更好地控制。 然而,由于附加的配置,该方法还导致增加的复杂性。 此外,您可能会遇到很多乏味的嘲笑。
对于这个简单的示例,使用模拟可能是解决方法。 但这并非总是如此。 如果是这样,另一种可能的方法是使用本地测试服务器。 碰巧的是,Apache HttpClient项目在其测试工件中提供了LocalTestServer。 如果您使用的是Maven,则可以通过添加以下依赖项将其包括在内:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.6</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
现在,您可以在单元测试中设置服务器:
LocalTestServer设置
private LocalTestServer server = new LocalTestServer(null, null);
@Before
public void setUp() throws Exception {
server.start();
}
@After
public void tearDown() throws Exception {
server.stop();
}
当然,仅启动和停止服务器并不能帮助您。 因此,您还需要另一种成分。 您将要注册一个或多个实现org.apache.http.protocol.HttpRequestHandler
接口的处理程序,例如:
注册您的处理程序
server.register("/foo/*", myHttpRequestHandler);
HttpRequestHanlder接口将让您实现方法void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException;
该方法将使您完全控制HTTP响应。
因此,对于我们的原始示例,最小的单元测试可能类似于以下代码:
基本单元测试
public class ExampleHttpCallTest {
private ExampleHttpCall exampleHttpCall;
private LocalTestServer server = new LocalTestServer(null, null);
private HttpRequestHandler myHttpRequestHandler = new HttpRequestHandler() {
@Override
public void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {
response.setEntity(new StringEntity("foobar"));
}
};
@Before
public void setUp() throws Exception {
server.start();
server.register("/foo/*", myHttpRequestHandler);
String serverUrl = "http:/" + server.getServiceAddress();
exampleHttpCall = new ExampleHttpCall(serverUrl +"/foo/bar");
}
@After
public void tearDown() throws Exception {
server.stop();
}
@Test
public void test() {
String result = exampleHttpCall.doGet();
assertEquals("foobar", result);
}
}
这就是开始所需要的全部。 从这里开始,您可以通过为每种可能的情况添加测试用例来进行详细说明。
翻译自: https://www.javacodegeeks.com/2015/08/unit-testing-http-calls-with-localtestserver.html