A more complex environment: web application based on a Web Server. Here we compare servious ways to simulate the Web Server Condition with Mock Object.
The original WebClient source:
src: http://blog.chinaunix.net/resserver.php?blogId=8755&resource=junit72.txt
As you can see java.net.HttpURLConnection and java.net.URL are related to the Web Server wanted to mock.
Someone may think directly: just mock it with its subclass as MockHttpURLConnetion and MockURL.
public void testGetContentOk() throws Exception {
MockHttpURLConnection mockConnection = new MockHttpURLConnection();
mockConnection.setupGetInputStream(new ByteArrayInputStream("It works".getBytes()));
MockURL mockURL = new MockURL();
mockURL.setupOpenConnection(mockConnection);
WebClient client = new WebClient();
String result = client.getContent(mockURL);
assertEquals("It works", result);
}
But one thing they forgot: the java.net.URL is a final class, which meants it couldnt be extended. Then, How can we mock it besides this way?
Now, we find we must do something to the class java.net.URL, let us easily to mock it.
improved src: http://blog.chinaunix.net/resserver.php?blogId=8755&resource=junit73.txt
You can find that with this alternaive we can mock it easiler.
private class TestableWebClient extends WebClient {
private HttpURLConnection connection;
public void setHttpURLConnection(HttpURLConnection connection) {
this.connection = connection;
}
public HttpURLConnection createHttpURLConnection(URL url) throws IOException {
return this.connection;
}
}
As you can see, with the class TestableWebClient extended from WebClient, you can set the HttpURLConnection yourself and artfully avoid the URL problem.
Test Case src with the improvement: http://blog.chinaunix.net/resserver.php?blogId=8755&resource=junit74.txt
"This is a common refactoring approach called Method Factory refactoring, which is especially useful when the class to mock has no interface. The strategy is to extend that class, add some setter methods to control it, and override some of its getter methods to return what you want for the test."
But what are you truely test? The subclass which behaviors have been changed, not the original one.