无法在单独的类中获取Executor的模拟实例

San*_*ani 3 unit-testing easymock mocking powermock executors

我试图从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;
    }
}    
Run Code Online (Sandbox Code Playgroud)

我的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果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());
        }
    }
Run Code Online (Sandbox Code Playgroud)

但是,如果我更改测试方法以调用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();
}
Run Code Online (Sandbox Code Playgroud)

我期望在myClass.myMethod中获得一个模拟的Executors/ExecutorService实例.

这是预期的行为吗?谁能解释一下这种行为?我错过了什么吗?

Wal*_*lls 5

你需要让班级知道会有一个Mock传入.在你的@PrepareForTest(),尝试还包括调用静态的类.这样你就可以告诉它模拟静态的执行,并告诉它这个模拟将在哪里发生.尝试更新@PrepareForTest({Executors.class, MyClass.class}).

如果你有它,所以你的测试类直接调用静态,你就有了Executors.class,@PrepareForTest()所以它会知道将这个模拟"注入"执行.当你调用你的另一个类时,在运行时你调用它的类不知道使用你的静态类的模拟版本,这就是为什么它使用它所知道的原始代码,而不是它的范围之外的模拟.添加CALLS静态对象(您测试的对象)的类将允许在运行时必须挂接静态模拟.