2017-01-13 4 views
1

Javaでテスト可能なコードを書く方法を学んでいます。単体テストをしたいのであれば、シングルトンクラスを実装するのは素晴らしいとは言いたくないリンクがたくさんあります。だから私は解決しようとしているものです。私は、HTTPリクエスト(HTTPRequestクラス)を送信するクラスを持っています。このクラスは、どのプロトコルを使用するか(TLSv1.2など)を心配してほしい。私はbody、URLなどでHTTPRequestクラスを呼び出す複数のクラスを持っています。シングルトンクラスを使用した依存性注入への移動方法

私が近づけたのは、同じ事の複数のインスタンスを作成する必要がないため、HTTPRequestはシングルトンクラスになることでした。プロジェクト全体のプロトコルは同じで、一度だけ設定する必要があります。

これは私のHTTPRequestの様子です。 1つのオブジェクトのみを使用してのGetRequestが、を呼び出す方法があるHTTPRequestの必要なクラスから今

public class HTTPRequest { 
    private CloseableHttpClient httpClient; 
    private HttpGet httpGet; 
    private HttpPut httpPut; 
    private HttpPost httpPost; 

    HTTPRequest(CloseableHttpClient a, HttpGet b, HttpPut c, HttpPost d) { 
     httpClient = a; 
     httpGet = b; 
     httpPut = c; 
     httpPost = d; 
    } 

    public HTTPResponse getRequest(url) { 
     //Do some processing with httpClient & httpGet to send the request 
    } 
} 

?私は依存性注入について何かを読んだが、私はそれをどうやってやるべきか本当に分かりません。

同様にテスト可能にするようにコードを変更する必要がありますか?

+0

コンストラクタのパラメータとして 'HttpGet'、' HttpPut'などを渡すのはなぜですか? – alayor

+0

@alayorまたは私はHttpGetの応答を嘲笑したい。私は実際に私のサーバーにそれを望んでいないので。 – user1692342

+0

しかし、 'getRequest'メソッドで' HttpGet'を渡すことができますか? – alayor

答えて

1

その後

public class HTTPRequest { 

    public HTTPResponse getRequest(url) { 
     //Do some processing with httpClient & httpGet to send the request 
     getHttpGet(url).call(); 
    } 

    protected CloseableHttpClient getHttpClient() { 
     return new CloseableHttpClient(); 
    } 

    protected HttpGet getHttpGet(String url) { 
     return new HttpGet(url); 
    } 

    protected HttpPost getHttpPost(String url) { 
     return new HttpPost(url); 
    } 

    ... 
} 

など、HTTPRequestクラスのコンストラクタを削除しgetHttpGet()と呼ばれるprotectedメソッドを作成し、getHttpPutである、あなたはHttpRequestとオーバーライドから継承HttpRequestMockクラスを作成することができますgetHttp*方法。

public class HTTPRequestMock extends HttpRequest { 

    @Override 
    protected CloseableHttpClient getHttpClient() { 
     //return mock 
     return new CloseableHttpClientMock(); 
    } 

    @Override 
    protected HttpGet getHttpGet(String url) { 
     //return mock 
     return new HttpGetMock(url); 
    } 

    @Override 
    protected HttpPost getHttpPost(String url) { 
     //return mock 
     return new HttpPostMock(url); 
    } 

    ... 
} 

最後に、あなたのユニットテストに応じHttpRequestまたはHttpRequestMockを注入することができます。

class HTTPRequestClient { 

    private HTTPRequest httpRequest = HttpRequestFactory.getHttpRequest(); 

    public void callServer(){ 
     httpRequest.getRequest("http://someurl.com/"); 
    } 

    void setHttpRequest(HTTPRequest httpRequest){ 
     this.httpRequest = httpRequest; 
    } 
    } 

class HTTPRequestFactory { 
    private static final HttpRequest httpRequest = new HttpRequest(); 

    public static HTTPRequest getHttpRequest() { 
    return httpRequest; 
    } 
} 

class HTTPRequestClientTest { 
    HTTPRequestClient httpRequestClient; 

     @Before 
     public void setUp(){ 
      httpRequestClient = new HTTPRequestClient(); 
      httpRequestClient.setHttpRequest(new HttpRequestMock()); 
     } 

     @Test 
     ... 
     } 
+0

詳細な説明をありがとう。しかし、私は様々なことをする複数のHTTPRequestClientsを持つことになります。私は各クラスのHTTPRequestの複数のオブジェクトを作成する必要はありません。 – user1692342

+0

'HTTPRequestFactory'を作成することができます。そして、あなたはただ一つの 'HTTPRequest'オブジェクトの作成を制御することができます。 – alayor

+0

多くの意味があります。私はそれを試してみる。ご協力いただきありがとうございます :) – user1692342

0

(注入フレームワークなし)依存性注入の単純な実装は、使用セッター作製することができる。上記の例で

class SomeOtherClass { 

    private HTTPRequest httpRequest; 
    public void setHttpRequest(HTTPRequest httpRequest){ 

    } 

    public void someAction(){ 
     httpRequest.getRequest(...); 
    } 
} 

... 
SomeOtherClass someOtherClass = new SomeOtherClass(httpRequest); 

を、HttpRequest(依存性)SomeOtherClassに注入されます。このようにして、単体テストではHttpRequestのモックを作成し、SomeOtherClassに提供し、外部依存関係なしでSomeOtherClassをテストすることができます。

それは意味がありますか?


、シングルトンについて:HttpRequestのシングルトンは(Mockitoのようなモックフレームワークを使用)モックにそれが難しくなります作ります。さらに、SomeOtherClassのようなクラスでは、HttpRequest.getInstance()を実行するだけでテストで何もできないようにすることができます。

+0

はい私はこれについて考えました。しかし、SomeOtherClassを呼び出す人がHttpRequestを作成する責任を負うことは望ましくありません。この場合、どうすれば対応できますか? – user1692342

+0

次に、SpringやGuiceのようなインジェクションフレームワークを使うことができます。フレームワークはオブジェクトをインスタンス化し、それらをあなたのbeanに挿入します。 – alexbt

+0

私はGuiceの例を見ていました。この場合、バインディングはどこで行われるべきですか? someotherclassはバインディングを行いますか?例を挙げることは可能でしょうか? – user1692342

0
  • beans.xmlという名前の空のファイルをWEB-INFディレクトリに置きます。
  • HttpRequestクラスに@ApplicationScopedと注釈を付けてください。
  • ローカルフィールドを使用するすべてのクラスにローカルフィールドを追加し、@Injectと注釈を付けます。あなたは何ができるか
関連する問題