I have the following class which contains a hard coded URL that never changes:
public class HttpClient {
private final String DOWNLOAD_URL = "http://original.url.json";
public String readJsonDataFromUrl() throws IOException {
URLConnection urlConnection = getUrlConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuffer content = new StringBuffer();
String readLine = "";
while ((readLine = reader.readLine()) != null) {
content.append(readLine);
}
return content.toString();
}
private URLConnection getUrlConnection() throws IOException {
URL jsonLocator = new URL(DOWNLOAD_URL);
return jsonLocator.openConnection();
}
}
Now imagine that I'd like to expect the IOException in my test. In my opinion, the only way to do that is to rewrite the complete class in a mock object because of the final variable:
public class HttpClientMock extends HttpClient {
private final String DOWNLOAD_URL = "http://wrong.test.url.json";
@Override
public String readJsonDataFromUrl() throws IOException {
URLConnection urlConnection = getUrlConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuffer content = new StringBuffer();
String readLine = "";
while ((readLine = reader.readLine()) != null) {
content.append(readLine);
}
return content.toString();
}
private URLConnection getUrlConnection() throws IOException {
URL jsonLocator = new URL(DOWNLOAD_URL);
URLConnection urlConnection = jsonLocator.openConnection();
return urlConnection;
}
}
But this is somehow far-fetched. If the original methods would be changed, the test results could still be positive because with this attempt, I don't actually test the original class anymore.
How can this be done properly? (I don't want to use a framework just for this one test, so are there any design attempts to solve this in a common way?)