web-dev-qa-db-ja.com

Mockitoを使用して保護されたメソッドをモックするにはどうすればよいですか?

Mockito 1.9.5を使用しています。保護されたメソッドから返されたものをモックするにはどうすればよいですか?私はこの保護されたメソッドを持っています...

protected JSONObject myMethod(final String param1, final String param2)
{
…
}

ただし、JUnitでこれを実行しようとすると:

    final MyService mymock = Mockito.mock(MyService.class, Mockito.CALLS_REAL_METHODS);        
    final String pararm1 = “param1”;
    Mockito.doReturn(myData).when(mymock).myMethod(param1, param2);

最後の行で、「メソッド「myMethod」は表示されません」というコンパイルエラーが表示されます。Mockitoを使用して保護されたメソッドをモックするにはどうすればよいですか?それが答えであるなら、私は私のバージョンをアップグレードすることに対してオープンです。

18
Dave

これはMockitoの問題ではなく、単純な古いJavaの問題です。メソッドを呼び出している場所からは、可視性がありません。これが、実行時の問題ではなく、コンパイル時の問題である理由です。

いくつかのオプション:

  • 模擬クラスと同じパッケージでテストを宣言する
  • 可能であれば、メソッドの可視性を変更します
  • モックされたクラスを拡張するローカル(内部)クラスを作成し、このローカルクラスをモックします。クラスはローカルであるため、メソッドを表示できます。
28
John B

John Bの回答からのオプション3のコードサンプルのリクエストへの応答:

public class MyClass {
    protected String protectedMethod() {
        return "Can't touch this";
    }
    public String publicMethod() {
        return protectedMethod();
    }
}

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {

    class MyClassMock extends MyClass {
        @Override
        public String protectedFunction() {
            return "You can see me now!";
        }
    }

    @Mock
    MyClassMock myClass = mock(MyClassMock.class);

    @Test
    public void myClassPublicFunctionTest() {
        when(myClass.publicFunction()).thenCallRealMethod();
        when(myClass.protectedFunction()).thenReturn("jk!");
    }
}
7
Nyefan

SpringのReflectionTestUtilsを使用して、クラスをそのまま使用することができ、テストのためだけに変更したり、別のクラスにラップしたりする必要はありません。

public class MyService {
    protected JSONObject myProtectedMethod(final String param1, final String param2) {
        return new JSONObject();
    }

    public JSONObject myPublicMethod(final String param1) {
        return new JSONObject();
    }
}

そして、テストで

@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {

    @Mock
    private MyService myService;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

        when(myService.myPublicMethod(anyString())).thenReturn(mock(JSONObject.class));
        when(ReflectionTestUtils.invokeMethod(myService, "myProtectedMethod", anyString(), anyString())).thenReturn(mock(JSONObject.class));
    }

}
1
nicmon

John Bが正しい。これは、テストしようとしているメソッドが保護されているためです。Mockitoの問題ではありません。

彼がリストしたものに加えて別のオプションは、リフレクションを使用してメソッドにアクセスすることです。これにより、テストするメソッドの変更を避け、テストの作成に使用するパターンやテストの保存場所の変更を避けることができます。ユニットテストが必要な多数のプライベートメソッドを含む既存のコードベースを変更することが許可されていない一部のテストでは、これを自分で行う必要がありました。

これらのリンクはReflectionとその使用方法を非常によく説明しているので、コピーするのではなく、それらにリンクします。

1
Seb

WhiteBox.invokeMethod()は便利です。

0
Smart Coder