测试中用 ExecutorService 替换 ManagedExecutorService

问题描述 投票:0回答:2

我有一些使用 Java EE 的服务

ManagedExecutorService
(在 Wildfly 9 中)

public class FooService{
    @Resource
    ManagedExecutorService executorService;
}

对于 Mockito 的测试,我想使用“正常”

ExecutorService

@RunWith(MockitoJUnitRunner.class)
public class FooServiceTest{
   @Spy
   ManagedExecutorService executorService = Executors.newFixedThreadPool(5);
}

这段代码显然无法编译,因为

ExecutorService
不是
ManagedExecutorService

在服务中使用

ExecutorService
时,测试运行没有错误,但是Wildfly无法注入服务。

public class FooService{
    @Resource
    ExecutorService executorService;
}

@RunWith(MockitoJUnitRunner.class)
public class FooServiceTest {
   @Spy
   ExecutorService executorService = Executors.newFixedThreadPool(5);
}

可以通过委托给

ManagedExecutorService
来创建
ExecutorService
:

@Spy
ManagedExecutorService executorService = new ManagedExecutorService() {

   ExecutorService executorService = Executors.newFixedThreadPool(5);
   @Override
   public void shutdown() {
       executorService.shutdown();
   }

   // delegate for all (12) methods
}

是否有更简单的方法可以在测试中使用

ExecutorService
而不更改Wildfly中运行的服务?

java jakarta-ee concurrency mockito wildfly
2个回答
0
投票

我使用注入模式:

class DefaultImpl {
 static DefaultFactory me;
 static DefaultFactory getCurrentInstance()
  { if (me == null) {
     me = new DefaultFactory();
    }
    return me;
  }
void setCurrentInstance(DefaultFactory df){
  me = df;
}
 ExecutorService getExecutorService(){
   // lookup and return ManagedExecutorService
 }
}
class TestImpl extends DefaultImpl{
  TestImpl(){
    DefaultFactory.setCurrentInstance(this); <-- this now sets your TestImpl for any call
  }
  ExecutorService getExecutorService(){
    ExecutorService executorService = Executors.newFixedThreadPool(5);
    return executorService;
  }
}

//junit
@Test
void someTest(){
 new TestImpl();
 // do something all your calls will use non managed executor service
}

您还可以从 junit setup() 调用 new TestImpl()。另外,如果您想让它更灵活,那么您可以拥有一个 BaseImpl 并让 DefaultImpl 和 TestImpl 扩展它。

希望这有帮助!


0
投票

如果有人仍在寻找答案:我嘲笑了

ManagedExecutorService
并使用
CompletableFuture.runAsync(...)
ExecutorService
组合来实现嘲笑的行为:

@ExtendWith(MockitoExtension.class)
class SomeServiceTest {

    @Mock
    private ManagedExecutorService managedExecutorService;
    @Mock
    private ServiceCalledAsyncly serviceCalledAsyncly;

    private SomeService someService;

    @BeforeEach
    void setUp() {
        var testExecutorService = Executors.newFixedThreadPool(10);
        when(managedExecutorService.runAsync(any())).then(invocation -> {
            Runnable runnable = invocation.getArgument(0);
            return CompletableFuture.runAsync(runnable, testExecutorService);
        });

        doAnswer((invocation) -> {
            Thread.sleep(1000);
            return null;
        }).when(serviceCalledAsyncly).doSomethingLongRunning();

        someService = new SomeService(managedExecutorService, serviceCalledAsyncly);
    }

    // your tests...
}
© www.soinside.com 2019 - 2024. All rights reserved.