2

変更されないハードコードされた URL を含む次のクラスがあります。

    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();
        }
    }

ここで、テストで IOException を期待したいとします。私の意見では、これを行う唯一の方法は、final 変数があるため、完全なクラスをモック オブジェクトに書き直すことです。

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;
    }
}

しかし、これはある意味大袈裟です。元のメソッドが変更されたとしても、テスト結果は依然として肯定的である可能性があります。これは、この試みでは元のクラスを実際にテストしていないためです。

どうすればこれを適切に行うことができますか?(この 1 つのテストのためだけにフレームワークを使用したくないので、これを一般的な方法で解決するための設計上の試みはありますか?)

4

2 に答える 2

0

皆さんに感謝しますが、Gilbert Le Blancのソリューションは、次のような場合に最も適していると思います。

元のクラス:

public class HttpClient {
    private final String DOWNLOAD_URL = "http://my.original.json.url";

    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(getConnectionString());

        return jsonLocator.openConnection();
    }

    protected String getConnectionString()  {
        return DOWNLOAD_URL;
    }
}

モックオブジェクト:

public class HttpClientMock extends HttpClient  {
    private String downloadUrl = "http://my.original.json.url";

    public HttpClientMock()  {
        super();
    }

    public HttpClientMock(String downloadUrl)  { 
        this.downloadUrl = downloadUrl;
    }

    @Override
    protected String getConnectionString()  {
        return downloadUrl;
    }
}

そして、作業テスト:

public class HttpClientTest {

    private JSONParser jsonParser = new JSONParser();

    @Test
    public void readJsonDataFromUrlSucceeds() throws IOException, ParseException {
        HttpClient httpClient = new HttpClientMock();

        String jsonString = httpClient.readJsonDataFromUrl();
        JSONObject jsonObject = (JSONObject)jsonParser.parse(jsonString);

        assertTrue(jsonObject.size() > 0);
    }

    @Test(expected = IOException.class)
    public void readJsonDataFromMalformedUrlFails() throws IOException, ParseException {
        HttpClient httpClient = new HttpClientMock("http://malformed");

        httpClient.readJsonDataFromUrl();
    }
}
于 2012-09-07T19:52:10.510 に答える
0

Gilbert Le Blanc の提案に対するもう 1 つの工夫は、コンストラクターを介して URL を注入することにより、HttpClient が URL を完全に認識しないようにすることです。

 public class HttpClient {
   private final String url;

   public HttpClient(String url) { this.url = url; }

 }

URL を HttpClient の外部のどこかにハードコーディング (または構成から読み取る) し、クライアントをインスタンス化する場所に挿入することができます。次に、テストで悪いURLを挿入するのは簡単です。

于 2012-09-07T19:32:54.347 に答える