32

私はGoogleGuiceにオブジェクトの配線の責任を与えました。しかし、バインディングがうまく機能しているかどうかをテストするにはどうすればよいですか?

たとえばA、依存関係を持つクラスがあるとしBます。Bが正しく注入されていることをどのようにテストできますか?

class A {
    private B b;
    public A() {}

    @Inject
    public void setB(B b) {
        this.b = b
    }
}

Aメソッドがないことに注意してください。メソッドがないgetB()ことを表明したいと思います。A.bnull

4

4 に答える 4

46

複雑なGuiceプロジェクトの場合は、テストを追加して、モジュールを使用してクラスを作成できることを確認する必要があります。あなたの例では、BがGuiceが作成方法を理解できないタイプである場合、GuiceはAを作成できません。Aがサーバーを起動する必要はなかったが、サーバーがリクエスト、それは問題を引き起こすでしょう。

私のプロジェクトでは、重要なモジュールのテストを作成します。モジュールごとに、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()上記の例では、呼び出しがない場合でもテストは機能しますが、ドキュメントとして機能するため、呼び出しが必要です。

より複雑なモジュール(ルートモジュールなど)の場合、Modules.override()を使用して、テスト時に不要なバインディングをオーバーライドできます(たとえば、ルートオブジェクトが作成されることを確認したい場合は、おそらくデータベースに接続するオブジェクトを作成したくない)。単純なプロジェクトの場合は、最上位モジュールのみをテストできます。

フィールドに注釈が付けられていない限り、Guiceはnullを挿入@Nullableしないため、テストで挿入されたオブジェクトがnullでないことを確認する必要はほとんどありません。実際、コンストラクターに注釈を付けるときは@Inject、パラメーターが正しいかどうかをわざわざチェックする必要はありませんnull(実際、nullテストを単純にするために、テストはコンストラクターに挿入されることがよくあります)。

于 2010-04-17T20:40:20.750 に答える
4

構成をテストするもう1つの方法は、アプリをエンドツーエンドでテストするテストスイートを用意することです。エンドツーエンドのテストは、名目上はユースケースをテストしますが、アプリが正しく構成されていることを間接的にチェックします(すべての依存関係が配線されていることなど)。一方、単体テストは、コードがデプロイされているコンテキストではなく、ドメインのみに焦点を当てる必要があります。

NamshubWriterの答えにも同意します。単体テストとは別のテストスイートにグループ化されている限り、構成をチェックするテストには反対しません。

于 2010-11-02T15:52:22.430 に答える
2

私見、あなたはそれをテストするべきではありません。Google Guiceの担当者は、インジェクションが期待どおりに機能することを確認するための単体テストを行っています。結局のところ、Guiceはそれを実行するように設計されています。自分のコード(AとB)のテストのみを作成する必要があります。

于 2010-03-15T15:37:20.173 に答える
0

設定されているプラ​​イベートメンバーをテストするべきではないと思います。クラスのパブリックインターフェイスに対してテストすることをお勧めします。メンバー「b」が挿入されない場合は、テストを実行するときにNullPointerExceptionが発生する可能性があります。これは、十分な警告となるはずです。

于 2010-03-15T15:00:42.643 に答える