7

プロジェクトで依存性注入を行うために Guice を使い始めました。主な理由は、単体テストから離れたレイヤーに (現在 JMock を使用して) モックを注入する必要があるためです。これにより、手動注入が非常に厄介になります。

私の質問は、モックを導入するための最良のアプローチは何ですか? 私が現在持っているのは、依存関係を満たす単体テストで新しいモジュールを作成し、次のようなプロバイダーにバインドすることです。

public class JMockProvider<T> implements Provider<T> {
    private T mock;

    public JMockProvider(T mock) {
        this.mock = mock;
    }

    public T get() {
        return mock;
    }
}

コンストラクターでモックを渡すため、JMock のセットアップは次のようになります。

    final CommunicationQueue queue = context.mock(CommunicationQueue.class);
    final TransactionRollBack trans = context.mock(TransactionRollBack.class);
    Injector injector = Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
            bind(CommunicationQueue.class).toProvider(new JMockProvider<QuickBooksCommunicationQueue>(queue));
            bind(TransactionRollBack.class).toProvider(new JMockProvider<TransactionRollBack>(trans));
        }
    });
    context.checking(new Expectations() {{
        oneOf(queue).retrieve(with(any(int.class)));
        will(returnValue(null));
        never(trans);
    }});
    injector.getInstance(RunResponse.class).processResponseImpl(-1);

より良い方法はありますか?AtUnit がこの問題に対処しようとしていることは知っていますが、上記のようにローカルで作成されたモックを自動的に魔法のように注入する方法がわかりませんが、ここで AtUnit が正しい答えである説得力のある理由 (その他) を探しています。テストを変更せずにDIとモックフレームワークを変更する能力よりも)、または手動で行うためのより良い解決策があるかどうか。

4

4 に答える 4

12

DIフレームワークを介してモックを注入する必要はありません。私はGuiceとJMockを非常にうまく使用していますが、単体テストではGuiceに関連するものは何も参照していません。私はモックのみを使用しnull、該当する場合はパスします。

DIを使用すると、現在のクラスの依存関係の挿入と構築が可能になるため、モックアウトされたクラス(依存関係グラフを効果的に停止する)を追加する場合は、それを渡す必要があります。MiskoHeveryはGoogleTechの1つで述べていますユニットテストの範囲は個々のユニットテスト方法にローカライズされているため、ユニットテストにはnew「s」と「s」を散らかす必要があるnullと話します。私は彼に同意する必要があります。

テストでGuiceを使用する必要がある理由はありますか?つまり、機能/統合テストではない場合ですか?

インジェクターを除外した場合、テストは機能しませんか?テストを次のようなものにリファクタリングできませんでした:

final CommunicationQueue queue = context.mock(CommunicationQueue.class);
final TransactionRollBack trans = context.mock(TransactionRollBack.class);

context.checking(new Expectations() {{
    oneOf(queue).retrieve(with(any(int.class)));
    will(returnValue(null));
    never(trans);
}});

RunResponse r = new RunResponse(queue, trans); // depending on the order
r.processResponseImpl(-1);
于 2010-01-12T05:29:41.060 に答える
1

あなたが言ったことから、実際の単体テストを行っていないようです。クラスの単体テストを行うときは、1 つのクラスだけに注目します。単体テストを実行するときは、テスト対象のクラスのみを実行し、関連するクラスからメソッドを実行しないようにする必要があります。

JMock/Easymock は、クラスの単体テストを実現するためのツールです。それらは統合テストでは役に立ちません。

単体テストのコンテキストでは、Guice は JMock/Easymock と重複しています。Guice は、JMock/Easymock と同じ結果を得るために、あらゆる種類の注釈 (@Inject など) でコードを汚染することをユーザーに強制します。Guice がテストに役立つという点で、私は Guice に強く反対しています。開発者が JMock/Easymock の代わりに Guice を使用することに気付いた場合、実際の単体テストを適切に実行しないか、コントローラー クラスをテストしようとします。

コントローラー クラスのテストは、単体テスト レベルではなく、統合テスト レベルで行う必要があります。統合テストでは、Jakarta Cactus を使用すると非常に役立ちます。統合テストでは、開発者はすべての依存関係を利用できるようにする必要があるため、Guice を使用する必要はありません。

結論として、製品のテストに Guice を使用する理由は見当たりません。Google Guice は、テスト以外のさまざまな状況で役立つ場合があります。

于 2010-04-05T05:17:25.043 に答える
0

Yishai、より良い設計を推進することは、Martin Fowler によって導入された Dependency Injection パターンの功績によるものであることを訂正する必要があります。Guice は、コードが既に DI パターンに従っている場合に役立つツールです。Guice は、コーディングの改善には何の貢献もしません。Guice はアドホックな方法で (注釈レベルで) DI を解決しているため、DI フレームワークとして使用することも考えるべきではありません。これが、Spring による xml ベースの DI コンテナと、Guice によるアノテーションベースの DI コンテナの大きな違いです。

クラスの単体テストが不可能であると言った理由を理解するために、最初に投稿されたコードを読むのに少し時間を費やしました(通常は読みません)。私は最終的にあなたが直面している問題を理解しています。単体テスト レベルで見たところ、Java EE サーバー内で実行されるコードの実行フローを模倣しようとしました。それがあなたが立ち往生した理由です。ここでのインセンティブが何であるかはわかりませんが、これらすべての環境依存関係を準備するためのあなたの努力が無駄になることを恐れています:(

単体テストを作成することは、使用しているテクノロジーに依存しない「ビジネス ロジック」をテストすることです。このビジネス ロジックは、 Quality of Service (QoS)環境内で実行する必要があるという別の要件がある場合があります。この要件が「技術要件」です。あなたの例では、CommunicationQueueTransactionRollBackは「技術的要件」を満たすためにほとんど機能しています。状況は、あなたの「ビジネス要件」がこれらすべての環境ユニットに囲まれているということです。「ビジネス要件」が依存関係のない分離されたメソッドになるように、コードをリファクタリングする必要があります。次に、これらのメソッドの単体テストを作成します。

私はまだ機能テストを行っていると考えています。単体テスト レベルで機能テストを行うのは非常に時間がかかり、そのようなことを行う価値もありません。役立つことを願っています

于 2010-04-09T02:53:24.977 に答える
0

Yishai さん、これらの依存関係を回避するには AOP が必要なようですね。AspectJ と AspectWerkz はどちらも便利なリソースです。ただし、AspectWekz には、JVM ホットスワップ テクノロジを使用して実行時にアスペクト クラスを織り込むという非常に優れた機能があります。もちろん、これらのエンジニアリング作業は単体テスト レベルでのみ適用する必要があります。

単体テストを行うとき、依存関係を解決するために多くの努力をしました。JMock、EasyMock、Java EE マイクロコンテナ、AspectJ、AspectWerkz、Spring IoC などのツールを使用して DI 問題を解決できます。これらのツールのどれも、開発者が製品コードにテスト意識を持たせることを促進していません。残念なことに、Guice は、あらゆる種類のテスト認識からコードをクリーンに保つという概念に違反しています。また、単体テストで使用するツールとしては数えません。

プロダクション コードから @Inject アノテーションを削除する十分な理由を説明できたことを願っています。

于 2010-04-11T04:32:18.663 に答える