4

java.util.concurrent パッケージから ExecutorService と Executors をモックしようとしています。

オブジェクトをモックしている同じクラス (テスト クラス) 内でオブジェクトを取得しようとすると、モックされたオブジェクトを取得できます。ただし、モックされたオブジェクトを別のクラス (テストしたいクラス) で取得しようとすると、java.util.concurrent から実際のオブジェクトが返されます。以下はコード スニペットです。

テストしたいクラス:

public class MyClass
{
    public void myMethod()
    {
        ExecutorService executorService = Executors.newFixedThreadPool(2, new MyThreadFactory());

        for (int count = 0; count < 2; count++)
        {
            executorService.submit(new Thread());
        }
    }
}

class MyThreadFactory implements ThreadFactory
{
    @Override
    public Thread newThread(Runnable r)
    {
        return null;
    }
}    

私の Test クラスは次のようになります。

@RunWith(PowerMockRunner.class)
@PrepareForTest(Executors.class)
public class MyClassTest
{
    @Test
    public void testMyMethod()
    {
        prepareMocks();            

        //Code to get mocked object (See testMethod below)
    }

    private void prepareMocks()
    {
        ExecutorService executorService = PowerMock.createMock(ExecutorService.class);
        EasyMock.expect(executorService.submit(EasyMock.anyObject(Runnable.class))).andReturn(null).anyTimes();

        PowerMock.mockStatic(Executors.class);
        EasyMock.expect(Executors.newFixedThreadPool(EasyMock.anyInt(), EasyMock.anyObject(ThreadFactory.class))).andReturn(executorService).anyTimes();

        PowerMock.replay(executorService, Executors.class);
    }
}

MyClassTest.testMyMethod() が以下の場合、モックされたオブジェクトを返します。

    @Test
    public void testMyMethod()
    {
        prepareMocks();

        //Following code reurned mocked instance of ExecutorService
        ExecutorService executorService = Executors.newFixedThreadPool(2, new MyThreadFactory());

        for (int count = 0; count < 2; count++)
        {
            executorService.submit(new Thread());
        }
    }

ただし、テスト メソッドを変更して myClass.myMethod() を呼び出すと、myMethod() のモック インスタンスではなく実際のインスタンスが返されます。

@Test
public void testMyMethod()
{
    prepareMocks();

    /*
     * Within myClass.myMethod(), Executors.newFixedThreadPool() returns actual instance of ThreadPoolExecutor
     * instead of mocked object
     */
    MyClass myClass = new MyClass();
    myClass.myMethod();
}

myClass.myMethod で Executors/ExecutorService のモック化されたインスタンスを取得することを期待しています。

これは予想される動作ですか?誰かが動作を説明できますか? 何か不足していますか?

4

1 に答える 1

7

Mock が着信することをクラスに知らせる必要があります。@PrepareForTest()に、静的を呼び出しているクラスも含めてみてください。このようにして、静的な実行をモックするように指示するだけでなく、このモックがどこで行われるかを伝えます。を更新してみてください@PrepareForTest({Executors.class, MyClass.class})

テストクラスが static を直接呼び出しているようにすると、 が含まExecutors.classれている@PrepareForTest()ため、そのモックを実行に「注入」することがわかります。他のクラスを呼び出す場合、実行時に呼び出しているクラスは、静的クラスのモック バージョンを使用することを認識していません。そのため、スコープ外のモックではなく、知っている元のコードに頼っています。 . 静的オブジェクト (テストするオブジェクト) を呼び出すクラスを追加すると、静的モックを実行時にフックする必要があります。

于 2013-12-18T15:16:58.267 に答える