どのように私は、Guiceの注射をテストするのですか?
-
20-09-2019 - |
質問
私はGoogleのGuiceのに私のオブジェクトを配線する責任を与えました。バインディングがうまく機能している場合でも、どのようにテストすることができますか?
たとえば、我々は依存A
を持つクラスB
があるとします。どのように私はBが正しく注入されていることをテストすることができますか?
class A {
private B b;
public A() {}
@Inject
public void setB(B b) {
this.b = b
}
}
そのA
がgetB()
メソッドを持っていません注意してください、私はそのA.b
を主張したいことはnull
ではありません。
解決
は、任意の複雑なGuiceのプロジェクトのために、あなたはモジュールがあなたのクラスを作成するために使用することができていることを確認するためのテストを追加する必要があります。あなたの例では、Bは、Guiceの作成する方法を見つけ出すことができなかったタイプであった場合は、Guiceのは、Aが、サーバを起動するために必要なされなかった場合はA.を作成することはできませんが、あなたのサーバが処理していた時に必要でした問題を引き起こす要求、ます。
私のプロジェクトでは、私は非自明モジュールのテストを書きます。各モジュールのために、私は<のhref = "http://google-guice.googlecode.com/svn/tags/2.0/javadoc/com/google/inject/AbstractModule.html#requireBinding%28java.lang.Class%29を使用します「REL =」nofollowをnoreferrer "> requireBindingは()モジュールが必要ですが、定義していないバインディングは何を宣言することを。私のテストでは、私がテストし、必要なバインディングを提供する別のモジュールの下のモジュールを使用してのGuiceインジェクタを作成します。ここでJUnit4とJMockを使用した例があります:
/** Module that provides LoginService */
public class LoginServiceModule extends AbstractModule {
@Override
protected void configure() {
requireBinding(UserDao.class);
}
@Provides
LoginService provideLoginService(UserDao dao) {
...
}
}
@RunWith(JMock.class)
public class LoginServiceModuleTest {
private final Mockery context = new Mockery();
@Test
public void testModule() {
Injector injector = Guice.createInjector(
new LoginServiceModule(), new ModuleDeps());
// next line will throw an exception if dependencies missing
injector.getProvider(LoginService.class);
}
private class ModuleDeps extends AbstractModule {
private final UserDao fakeUserDao;
public ModuleDeps() {
fakeUserDao = context.mock(UserDao.class);
}
@Override
protected void configure() {}
@Provides
Server provideUserDao() {
return fakeUserDao;
}
}
}
テストは唯一のプロバイダを要求する方法に注目してください。それはGuiceのバインディングを解決することができることを決定するのに十分です。 LoginServiceは、プロバイダメソッドによって作成された場合、このテストは、プロバイダの方法でコードをテストしません。
このテストは、あなたがUserDao
には正しいことをバインドさ、またはそのUserDao
が正しくスコープされたことをテストするものではありません。いくつかは、物事のこれらのタイプはチェックまれ価値があることを主張するだろう。問題がある場合は、それが一度起こります。 「恐怖は退屈になるまでテストが。」あなたがすべき
私は、多くの場合、新しい注入点を追加したため、モジュールが有用テストし、それが結合を追加することを忘れやすいです見つけます。
requireBinding()
コールは、それはあなたのインジェクタを返す前に、Guiceのが欠落しているバインディングをキャッチすることができます!上記の例では、requireBinding()
呼び出しはありませんがあった場合、テストはまだ動作しますが、私は、彼らがドキュメントとしての役割を果たすので、それらを持っているような。
私が使用する可能性があります(私のルートモジュールのような)より複雑なモジュールの場合は<のhref = "http://google-guice.googlecode.com/svn/trunk/latest-javadoc/com/google/inject/util/Modules .htmlを#オーバーライド%の28com.google.inject.Module ...%が29" のrel = "nofollowをnoreferrer"> Modules.overrideは()、例えば(テスト時に私はしたくないバインディングを上書きするを私は私のルートオブジェクトを作成することを確認したい場合、私はおそらく)それがデータベースに接続するオブジェクトを作成する必要はありません。シンプルなプロジェクトでは、あなただけのトップレベルのモジュールをテストすることがあります。
Guiceのフィールドない限り@Nullable
で注釈としてのヌルを注入しないことに注意してくださいあなたは非常に稀に注入されたオブジェクトは、あなたのテストで非nullであることを確認する必要がありません。実際に、私は@Inject
でコンストラクタに注釈を付けるとき、私はパラメータがnull
(実際には、私のテストは、多くの場合、簡単なテストを保つためにコンストラクタにnull
を注入)されているかどうかを確認するために気にしないでください。
他のヒント
設定をテストするもう一つの方法は、あなたのアプリケーションのエンドツーエンドをテストするテストスイートを持つことです。エンド・ツー・エンドのテスト名目上のテストのユースケースが、それらは間接的に(すべての依存関係が配線されていること、などなど)、アプリが正しく設定されていることを確認してください。一方、ユニットテストは、ドメイン上ではなく、あなたのコードが展開されるコンテキストに専念する必要があります。
私はまたNamshubWriterの答えに同意します。アイム彼らはあなたのユニットテストに別々のテストスイートにグループ化されている限り、設定を確認するテストは反対ではないと思います。
IMHO、あなたはそれをテストするべきではありません。 GoogleのGuiceのみんなは期待通り注射が動作することを主張するユニットテストを持っている - 結局のところ、それはGuiceのが行うように設計されているものです。あなただけの独自のコード(AおよびB)のためのテストを書く必要があります。
私はあなたがプライベートメンバーが設定されてテストする必要はないと思います。より良いあなたのクラスのパブリックインターフェイスに対してテストします。メンバー「b」が注入されることはない場合、あなたはおそらく、警告がたくさんあるべき、テストを実行するとNullPointerExceptionを取得します。