存在すると想定されるプライベート変数をモックする 質問する

存在すると想定されるプライベート変数をモックする 質問する

テスト対象のクラスでモック オブジェクトが作成/初期化されていない場合、モック オブジェクトが静的ではない場合 (シングルトン パターン)、またはフックするテスト コンストラクターがない場合、実行時にモック オブジェクトを取得するにはどうすればよいでしょうか。

ユニット テストを記述しているクラスで、まだ遭遇/解決していないシナリオに遭遇しました。QueueConnectionFactoryテストしているクラスのプライベート変数である JMS リソース (参照用ですが、問題にはなりません) があります。アノテーションがあるためjavax.annotation.Resource、実行時には使用可能であると想定されます。テスト中は使用できないため、このオブジェクトをモック化する必要があります。

これは静的クラスではなく、静的な方法で使用されていません。静的な方法で使用されていた場合、私が遭遇したさまざまな静的モック メソッドを使用して簡単にモックできます。リソースはローカルで作成されることはありません (コンストラクター内またはテスト コンストラクター内でさえ)。そのため、テストの実行時に実際のオブジェクトの代わりにモックが使用されるように、モック オブジェクトを渡す方法はありません。テストの実行時に、テストしているクラスのプライベート オブジェクトの代わりにこのリソースが使用されるようにするには、このリソースをモックするにはどうすればよいです@Resourceか。

参考までに、コードは を呼び出していますcreateConnection()が、QueueConnectionFactoryFactory が初期化/モック化されていないため、null ポインター例外がスローされています。

@Stateless
public class Example{
  @Resource(name = "jms/exampleQCF")
  private QueueConnectionFactory queueFactory;

  ...

  public void testMe(){
    Connection connection = queueFactory.createConnection();
    ...
  }
}

ベストアンサー1

さらにいろいろ調べて、Mockito/Powermock が提供するすべてのオプションを確認した後、解決策を見つけました (他の人も同じ問題に遭遇した場合に備えて、この解決策を共有します)。

初期化されることのない (そして他の場所で作成されたと想定される) プライベート メンバー変数がある場合、アノテーションを使用して、テストしているクラスに必要なモックを「挿入」できます@InjectMocks

  1. テストするクラスの変数をテスト クラスに追加し、アノテーション@InjectMocks(org.Mockito.InjectMocks) を付けます。
  2. @Mock挿入するモックを設定するには、アノテーションを使用します。name@Mock (name = "privateVariableNameHere")プロパティを使用して、Mock オブジェクトをテストするクラス内のプライベート変数にマップします。
  3. セットアップ関数内、またはクラスを呼び出す前に、モックを初期化します。私が見つけた最も簡単な方法は、アノテーション付きの「setup」メソッドを使用することです@Before。次に、その内部で呼び出して、アノテーションMockitoAnnotations.initMocks(this);付きのものをすばやく初期化します@Mock
  4. テスト メソッドで Mock 機能を定義します (テストするメソッドを呼び出す前に)。
  5. オブジェクトを使用して@InjectMock、テストしているメソッドを呼び出します... モックはフックされ、前の手順で定義したとおりに動作する必要があります。

したがって、上で使用したサンプル クラスの場合、テスト/モックするコードは、Connection何でもできるモックとして返されます。私の質問の上記の例に基づくと、コードは次のようになります。

@RunWith(PowerMockRunner.class)
@PrepareForTest({/* Static Classes I am Mocking */})
public class ExampleTest {
  @Mock (name = "queueFactory") //same name as private var.
  QueueConnectionFactory queueFactoryMock;
  @Mock
  Connection connectionMock; //the object we want returned
  @InjectMocks
  Example exampleTester; //the class to test

  @Before
  public void setup(){
    MockitoAnnotations.initMocks(this); // initialize all the @Mock objects
    // Setup other Static Mocks
  }

  @Test
  public void testTestMe(){
    //Mock your objects like other "normally" mocked objects
    PowerMockito.when(queueFactoryMock.createConnection()).thenReturn(connectionMock);
    //...Mock ConnectionMock functionality...
    exampleTester.testMe();
  }
}

おすすめ記事