相关文章推荐
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams public void execute() { ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(this::launch);

and I tried to mock Executors.newSingleThreadExecutor() to have an executorService that runs on the same thread as my tests, so that my assertions happens after the executions of the executorService and not before:

@RunWith(PowerMockRunner.class)
@PrepareForTest({
        AnOtherClass.class,
        Executors.class
public class TestClass {
    @Before
    public void setUp() throws Exception {
        PowerMockito.mockStatic(Executors.class);
        ExecutorService executorService = mock(ExecutorService.class);
        implementAsDirectExecutor(executorService);
        PowerMockito.when(Executors.newSingleThreadExecutor()).thenReturn(executorService);
    private void implementAsDirectExecutor(ExecutorService executor) {
        doAnswer(invocation -> {
            Object[] args = invocation.getArguments();
            Runnable runnable = (Runnable)args[0];
            runnable.run();
            return null;
        }).when(executor).submit(any(Runnable.class));
    @Test
    public void testMethod() {
       classToTest.execute();
       .... //assert something

Problem :

Even with PowerMockito.when(Executors.newSingleThreadExecutor()).thenReturn(executorService); the real method is called, and I don't get the mocked ExecutorService.

That method is wrong. It creates a new executor every call, and the executor is non-daemon. Don’t try and unit test it, fix it. – Boris the Spider May 5, 2021 at 8:02 Why do you want to mock an ExecutorService? Why not inject an executor into ClassToTest as a constructor parameter (or a Supplier<ExecutorService>), so you can create the instance you want, without mocking. – Andy Turner May 5, 2021 at 8:10

Solution 1

This issue could be resolved by adding the ClassToTest to the @PrepareForTest also.

@PrepareForTest({
        AnOtherClass.class,
        Executors.class,
        ClassToTest.class

Solution 2

But I prefer the solution of @Andy, it's more clean:

I passed my ExecutorService in the constructor of ClassToTest, and like that, I get rid of PowerMock:

public class ClassToTest{
    public ClassToTest(ExecutorService executorService) {
    public void execute() {
        executorService.submit(this::launch);

A different way to think about this is to inject the ExecutorService into the test-class for testing purposes:

public class ClassToTest {
   private ExecutorService testExecutor;
   public void execute() {
       ExecutorService executor;
       if (testExecutor == null) {
           executor = Executors.newSingleThreadExecutor();
       } else {
           executor = testExecutor;
       executor.submit(this::launch);
    public void setTestExecutor(ExecutorService testExecutor) {
        this.testExecutor = testExecutor;

Then you can use more standard interface mocking with PowerMockito as opposed to overriding the static classes.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.

 
推荐文章