How to use JUnit to test asynchronous processes

前端 未结 18 1619
小蘑菇
小蘑菇 2020-11-29 15:06

How do you test methods that fire asynchronous processes with JUnit?

I don\'t know how to make my test wait for the process to end (it is not exactly a unit test, it

18条回答
  •  醉梦人生
    2020-11-29 15:37

    One method I've found pretty useful for testing asynchronous methods is injecting an Executor instance in the object-to-test's constructor. In production, the executor instance is configured to run asynchronously while in test it can be mocked to run synchronously.

    So suppose I'm trying to test the asynchronous method Foo#doAsync(Callback c),

    class Foo {
      private final Executor executor;
      public Foo(Executor executor) {
        this.executor = executor;
      }
    
      public void doAsync(Callback c) {
        executor.execute(new Runnable() {
          @Override public void run() {
            // Do stuff here
            c.onComplete(data);
          }
        });
      }
    }
    

    In production, I would construct Foo with an Executors.newSingleThreadExecutor() Executor instance while in test I would probably construct it with a synchronous executor that does the following --

    class SynchronousExecutor implements Executor {
      @Override public void execute(Runnable r) {
        r.run();
      }
    }
    

    Now my JUnit test of the asynchronous method is pretty clean --

    @Test public void testDoAsync() {
      Executor executor = new SynchronousExecutor();
      Foo objectToTest = new Foo(executor);
    
      Callback callback = mock(Callback.class);
      objectToTest.doAsync(callback);
    
      // Verify that Callback#onComplete was called using Mockito.
      verify(callback).onComplete(any(Data.class));
    
      // Assert that we got back the data that we expected.
      assertEquals(expectedData, callback.getData());
    }
    

提交回复
热议问题