When you test-drive, you create the seams that support your testing intent. Recognizing that the retrieve()
method (Listing 14-2)
• Was a bit long
• Had no ready-made seams with which to sever the network connection for testing
• And performed a wide variety of low-level mechanics in support of its purpose
I decided to simplify and encapsulate it before continuing. Commit [c602d34] was the first application of this principle for WebRetriever.
public String retrieve(String URI) throws IOException {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(URI);
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
StringWriter writer = new StringWriter();
IOUtils.copy(content, writer);
return writer.toString();
}
Looking at the method, you can categorize it as setup, execution, and response processing, very much like the first three phases of a test. Unlike a test, you do not need to preserve the boundaries between the phases when you refactor. I chose to extract the retrieval of the response, consisting of set up and execution, as a single method (Listing 14-3).
public String retrieve(String URI) throws IOException {
HttpResponse response = retrieveResponse(URI);
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
StringWriter writer = new StringWriter();
IOUtils.copy(content, writer);
return writer.toString();
}
protected HttpResponse retrieveResponse(String URI)
throws IOException {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(URI);
return httpClient.execute(httpGet);
}
The following commits, through [c1d4b2f], use EasyMock to exploit the seam, although in an ugly and implementation-coupled way. That will be addressed in time. The commits through [b61f107] do some additional refactoring to improve both the test and the code under test in preparation for the next feature.
18.220.245.233