web-dev-qa-db-ja.com

Mockito:モックプライベートフィールドの初期化

インラインで初期化されているフィールド変数をモックするにはどうすればよいですか?

例えば.

class Test {
    private Person person = new Person();
    ...
    public void testMethod() {
        person.someMethod();
        ...
    }
}

ここで私はモックしたいperson.someMethod()メソッドのテスト中-Test#testMethod。

そのために、個人変数の初期化を模擬する必要があります。どんな手掛かり?

編集:Personクラスを変更することはできません。

53
Arun

私はすでにこの問題の解決策を見つけましたが、ここに投稿するのを忘れました。

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Test.class })
public class SampleTest {

@Mock
Person person;

@Test
public void testPrintName() throws Exception {
    PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
    Test test= new Test();
    test.testMethod();
    }
}

このソリューションの重要なポイントは次のとおりです。

  1. PowerMockRunnerでテストケースを実行する:@RunWith(PowerMockRunner.class)

  2. プライベートフィールドの操作のためにTest.classを準備するようにPowermockに指示します:@PrepareForTest({ Test.class })

  3. 最後に、Personクラスのコンストラクターをモックします。

    PowerMockito.mockStatic(Person.class);PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);

18
Arun

Mockitoには、いくつかの反射ボイラープレートコードを保存するヘルパークラスが付属しています。

import org.mockito.internal.util.reflection.Whitebox;

//...

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    Whitebox.setInternalState(underTest, "person", mockedPerson);
    // ...
}

更新:残念ながら、mockitoチームは クラスを削除する をMockito 2に決定しました。コード、別のライブラリを使用する(例: Apache Commons Lang )、または単に Whitebox クラスを盗む( MITライセンス )。

更新2:JUnit 5には、独自の ReflectionSupport および AnnotationSupport が役立つクラスが付属しています。さらに別のライブラリを使用しないようにしてください。

72
Ralf

パーティーにかなり遅れましたが、私はここで打たれ、友人から助けを受けました。事はPowerMockを使用することではありませんでした。これは、Mockitoの最新バージョンで動作します。

Mockitoにはこのorg.mockito.internal.util.reflection.FieldSetterが付属しています。

基本的には、リフレクションを使用してプライベートフィールドを変更するのに役立ちます。

これがあなたの使い方です-

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person", mockedPerson);
    // ...
    verify(mockedPerson).someMethod()

}

これにより、モックオブジェクトを渡して、後で検証することができます。

参照:

https://www.codota.com/code/Java/methods/org.mockito.internal.util.reflection.FieldSetter/set

14
Raj Kumar

Spring Testを使用する場合org.springframework.test.util.ReflectionTestUtils

 ReflectionTestUtils.setField(testObject, "person", mockedPerson);
8
Zimbo Rodger

次のコードを使用して、RESTクライアントモックでマッパーを初期化できます。 mapperフィールドはプライベートであり、単体テストのセットアップ中に設定する必要があります。

import org.mockito.internal.util.reflection.FieldSetter;

new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());
6

すべてのテストで変数に同じ値を設定する必要がある場合は、@ Jardaのガイドを使用してこれを定義できます。

@Before
public void setClientMapper() throws NoSuchFieldException, SecurityException{
    FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper());
}

ただし、プライベート値を異なる値に設定する場合は注意が必要です。彼らがプライベートである場合は、何らかの理由です。

たとえば、ユニットテストでスリープの待機時間を変更する場合などに使用します。実際の例では10秒間スリープしたいのですが、単体テストではすぐに満足します。統合テストでは、実際の値をテストする必要があります。

3
Hugo Dias