有时候,当您正在对远程服务器进行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 {@Resourceprivate 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() {@Overridepublic void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException {response.setEntity(new StringEntity("foobar"));}};@Beforepublic void setUp() throws Exception {server.start();server.register("/foo/*", myHttpRequestHandler);String serverUrl = "http:/" + server.getServiceAddress();exampleHttpCall = new ExampleHttpCall(serverUrl +"/foo/bar");}@Afterpublic void tearDown() throws Exception {server.stop();}@Testpublic void test() {String result = exampleHttpCall.doGet();assertEquals("foobar", result);}}
这就是开始所需要的全部。 从这里开始,您可以通过为每种可能的情况添加测试用例来进行详细说明。
翻译自: https://www.javacodegeeks.com/2015/08/unit-testing-http-calls-with-localtestserver.html