Webサービス呼び出しを必要とするクラスを単体テストするにはどうすればよいですか?


21

いくつかのHadoop Webサービスを呼び出すクラスをテストしようとしています。コードはほぼ次の形式です。

method() {
    ...use Jersey client to create WebResource...
    ...make request...
    ...do something with response...
}

たとえば、ディレクトリ作成メソッド、フォルダ作成メソッドなどがあります。

コードが私が制御できない外部Webサービスを処理していることを考えると、これをどのように単体テストできますか?Webサービスのクライアント/レスポンスをモックすることはできましたが、最近見た「所有していないオブジェクトをモックしないでください」というガイドラインに違反しています。ダミーのWebサービス実装をセットアップできます。それでも「単体テスト」を構成できますか、それとも統合テストになりますか?この低いレベルで単体テストを実行することはできませんか?TDD実践者はどのようにこれに取り組むのでしょうか?


5
自分が所有していないものをm笑しないというガイダンスを見たことがありますか?それはあなたが物事を
トーマスオーエンズ

1
私はそれを多くのブログで読みましたが、そのうちの1つはamazon.com/Growing-Object-Oriented-Software-Guided-Tests/dp/を参照しています。これはよく知られた本(blog.8thlight。 com / eric-smith / 2011/10/27 / thats-not-yours.htmlmockobjects.com /2007/04/test-smell-everything-is- mocked.html
クリスクーパー

1
@ChrisCooper:最後のリンクが非常に古い(2007年以降)ことを指摘できますか。それ以来、ロットは変化しています。投稿から、モックフレームワークまたはメタプログラミングを使用して戻り値を設定するのではなく、実際に動作を実装する必要があったときよりもモックがはるかに困難だったと感じています
...-c_maker

回答:


41

私の意見では、統合テストとは対照的に、これが単体テストである場合は、Webサービス呼び出しをモックする必要があります。

単体テストでは、外部Webサービスが機能しているかどうか、または外部Webサービスとの統合が正しいかどうかをテストしないでください。TDDについて独断的になりすぎることなく、単体テストを統合テストに変えることの副作用は、実行速度が遅くなる可能性があり、高速な単体テストが必要になることに注意してください。

また、Webサービスが一時的にダウンしているか、正しく機能していない場合、これによりユニットテストが失敗しますか?それは正しくないようです。ユニットテストが失敗するのは、その「ユニット」のコードにバグがある場合のみです。

ここで関連するコードの唯一の部分は...do something with response...です。残りをモックします。


2
モックオブジェクトの署名を保持し、そのサービスへの避けられない変更を通して、Hadoop Webサービスによって生成された値と同期した値を返す必要があることに注意してください。
-pcurry

Hadoopのような既製のコンポーネントをテストする価値はほとんどありません。ただし、別のチームまたは組織が提供するカスタムWebサービスを呼び出す場合は、自己防衛でテストを作成することをお勧めします。そうすれば、問題が発生したときに、問題がコードなのかWebサービスなのかをすばやく確認できます。これは自動的に実行される単体テストではありません。必要に応じて実行する診断です。
ケビンクライン14

@kevincline私はあなたが提案するテストの必要性に完全に同意し、実際に私は私の仕事でそれらを書き、それ自体が有用であることを証明しました。しかし、それらは定義上単体テストではなく、それが質問の目的でした:)これを考慮してください:単体テストであり、Webサービスが変更されたためコードが失敗した場合、テストしている「ユニット」は何ですか?何が正確に失敗しましたか?単体テストの必要に応じて、単独でテストすることはありません。
アンドレスF.

1
@AndresF .:私たちは激しい合意に達していると思います:「この[診断]はユニットテストではありません...」
ケビンクライン

@kevincline右!コメントを読み間違えました、ごめんなさい!
アンドレスF.

5

あなたがユニットテストをしているとき、私は「あなたが所有していないオブジェクトをモックしないでください」に同意しません。

モックの存在の目的は、所有しないモジュール、ライブラリ、クラスがあるという事実です。

あなたのシナリオに対する私の提案は、Webサービス呼び出しを模擬することです。

モジュールにデータを返すようにモックをセットアップします。
返されたデータがnullの場合、返されたデータが有効な場合など、すべてのシナリオを必ずカバーしてください。

また、所有するコードの場合、開発者としての責任は、オーサリングするコードがすべてのシナリオで期待どおりに実行されることを確認することです。


1

このテストにはEasyMockなどを使用します。モックフレームワークは、クラスの外部依存関係を削除する理想的な方法であり、テスト中に外部依存関係の結果を完全に制御できます。例を少し拡張するには:

class WebClass {

private WebServiceInterface webserviceInterface;

    void method(){
        R result = webServiceInterface.performWebServiceCall();
        ... do something with result
    }

    public void setWebServiceInterface(WebServiceInterface webServiceInterface){
        this.webServiceInterface = webServiceInterface;
    }
}


interface WebServiceInterface {

   R performWebServiceCall();

}


class WebClassTest {

private WebServiceInterface mock;    
private R sampleResult = new R();

    @Before
    public void before(){
        mock = EasyMock.createMock(WebServiceInterface.class);
    }


    @Test
    public void test() {
        WebClass classUnderTest = new WebClass();
        EasyMock.expect(mock.performWebServiceCall()).andReturn(sampleResult);
        classUnderTest.setWebServiceInterface(mock);
        classUnderTest.method();
        EasyMock.verify(mock);
    }
}

最初に行う必要があるのは、Jerseyを使用してWebResourceを取得し、Webサービスを別のクラスに呼び出すために、クラス内のロジックを抽出することです。このクラスのインターフェイスを作成すると、モックを作成して、動作を指示することができます。

このインターフェイスを作成したら、EasyMockを使用してモックを作成できます。これにより、テストケースに応じて指定されたオブジェクトが返されます。上記の例は、基本的な模擬テストを構成する方法と、インターフェイスがどのように機能するかを単純化したものです。

モックフレームワークの詳細については、この質問をご覧ください。また、この例ではJavaの使用を想定していますが、モックフレームワークはすべての言語で利用可能であり、実装方法は異なりますが、通常は同じように動作します


1

この場合、モックは許容されますが、必要ありません。単体テストの代わりにmethod()、代わりに応答を処理する部分のみを単体テストします。

ResponseData(適切な種類の)を受け取る関数を抽出し、アクションを実行します。

モックの代わりに、ResponseDataオブジェクトを作成して渡すだけです。

サービスの呼び出しは完全な統合テストに任せることができます-これはmethod()合計でカバーします


0

私がやったこと、そしてそれは動作します:

  1. すべてのコードがプロキシ経由でWebサービスを呼び出すようにします。
  2. プロキシは、プロキシを使用しているかどうかを静的に認識し、それに応じてリダイレクトするクラスを呼び出します。モックは、各リクエストに対して特定の応答を返す単なるHashMapです。
  3. この順序でテストを数回実行します。

3.1最初に、すべてのWebサービスがテストされます。開発者のマシンも含め、各マシンから。これらは実際のWebサービスですが、開発環境で実行されています。これは、すべての開発者がコンパイルできないと文句を言うため、Webサービスがダウンしたり、誤った値に応答したりすることがないことを意味します。

3.2その後、アプリケーション内部のすべての単体テストが実行されます。これは、3.1と同じテストを実行してすべてのWebサービスがモックされ、テストされ(テストはパスする必要があり、そうでない場合はモックが間違っている)、実際のアプリケーションによって実際に使用されているかのように呼び出されることを意味します。モックが間違っている場合は、3.1でテストを実行し、それらの値(要求、応答)をHashMapに記録できます。

3.3次に3.2と同じテストが実行されますが、今回は開発環境で実行されている実際のWebサービスに対して実行されます。

これらすべてが完了した後、実際の実稼働環境では、各Webサービスの実際のアドレスを提供するだけです。うまくいけば、これは構成の変更をあまり必要としません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.