web-dev-qa-db-ja.com

Java:フィールドが公開されていないときに、フィールドのメソッドをモックするにはどうすればよいですか?

Java 6、JUnit 4.8.1を使用して、コンソールアプリケーションを作成しています。私のアプリケーションには、公開されていないメンバーフィールドがあります…

_public class MyApp { 
    ...
    private OpportunitiesService m_oppsSvc;

    private void initServices() { 
        …
        m_oppsSvc = new OpportunitiesServiceImpl();
    }
    ...
}
_

サービスから1つのメソッドが呼び出されるたびに(たとえば、m_oppsSvc.getResults())、同じ結果が常に返されるような動作をモックしたいと思います。それ、どうやったら出来るの?フィールドのセッターメソッドはありません。私は現在Mockito1.8.4を使用しています。 Mockitoまたは他のモックフレームワークでこれを行うことは可能ですか?

14
Dave

これはあなたが望むものです:

@RunWith(MockitoJUnitRunner.class)
public class MyAppTest { 

    @Mock private OpportunitiesService mocked_m_oppsSvc;
    @InjectMocks MyApp myApp;

    @Test public void when_MyApp_uses_OpportunititesService_then_verify_something() { 
        // given
        given( mocked_m_oppsSvc.whatever()).willReturn(...);

        // when
        myApp.isUsingTheOpportunitiesService(...);

        // then
        verify...
        assertThat...
    }
}

使用: Mockito 1.9.BDDスタイル 、 FEST-アサートAssertJ

お役に立てば幸いです:)

12
Brice

すでにmockitoを使用している場合は、リフレクションを使用しないのはなぜですか。

@RunWith(MockitoJUnitRunner.class)
public class MyApp { 

    @Mock
    private OpportunitiesService m_oppsSvc;

    private MyApp myApp;


    @Before
    public void before() throws Exception {
       myApp = new MyApp();
       Field f = MyApp.class.getDeclaredField("m_oppsSvc");
       f.setAccessible(true);
       f.set(myApp, m_oppsSvc);
    }
}

それは少し醜いですが、それはトリックを行います。これはMockitoでそれを行うための最も効率的な方法ではないかもしれませんが、それは機能することに注意してください。

Whiteboxクラスを使用してこれを行うこともできるPowermockもあります。 Powermockの詳細については詳しく説明しませんが、プライベートフィールド値を挿入するための呼び出しは次のとおりです。これはモックオブジェクトである必要があります。

Whitebox.setInternalState(myApp, "m_oppsSvc", m_oppsSvc);
8
Matt

プライベートフィールドをモックする試みを検討する必要があります smell 。つまり、実行しようとしていることが正しくないか、コードが現在正しく構造化されていないことを示しています。パブリックメソッドまたは挿入された依存関係をモックするだけで済みます

指定したコードでは、次のようにOpportunitiesServiceを挿入することを検討する必要があります。

public class MyApp { 
    ...
    private OpportunitiesService m_oppsSvc;

    public MyApp(OpportunitiesService oppsSvc) {
        this.m_oppsSvc = oppsSvc;
    }
    ...
}

テストでは、次のようにモックを挿入できます。

OpportunitiesService mockOpportunitiesService =
    Mockito.mock(OpportunitiesService.class);
Mockit.when(mockOpportunitiesService.someMethod()).thenReturn(someValue);
MyApp app = new MyApp(mockOpportunitiesService);
6
munyengm

JMockitで簡単に行うことができます。

public class MyAppTest
{
    @Tested MyApp myApp;

    @Test
    public testSomething(final @Capturing OpportunitiesService mockService)
    {
        new NonStrictExpectations() {{
            mockService.getResults(); result = asList("a", "b", "C");
            // record other expectations, if needed
        }};

        myApp.whateverMethodIWantToTest();

        new Verifications() {{
            mockService.doSomething(anyInt);
            // verify other expectations, if needed
        }};
    }
}

実装クラスOpportunitiesServiceImplはテストコードで言及されていませんが、そのインスタンス(任意の数)は適切にモックされます。

0
Rogério