【问题标题】:How to test @Async Spring methods with junit?如何用junit测试@Async Spring方法?
【发布时间】:2022-02-01 12:18:01
【问题描述】:

我有一个@Async 方法并想用junit 对其进行测试。 问题:我希望 junit 在不阻塞的情况下触发对 async 方法的所有调用,所以不想要结果。

但在我下面的示例中,每个调用首先等待异步方法返回,然后继续下一个 incovation:

@Service
public class MainService {
    @Autowired
    private SubService sub;
    
    @Async
    public void processAsync() {
        sub.run();
    }
}


@SpringBootTest
public class MainServiceTest {
    @Autowired
    private MainService service;

    @MockBean
    private SubService sub;
    
    @Test
    public void testAsync() {
        final CountDownLatch latch = new CountDownLatch(5);
    
        when(sub.run()).then((answer) -> {
            latch.countDown();
            latch.await(); //return when latch is 0
            return;
        }
        
        for (int i = 0; i<6; i++) {
            //TODO this currently runs in sync. why?
            service.processAsync();
        }
    }   
}

我希望所有服务调用都阻塞,直到闩锁计数达到 0,然后继续测试。

但我得到的是 SubService 只被调用一次,然后卡在模拟的 Answer 方法中。

问题:为什么我在 @Test 方法中的 service.process() 调用没有直接触发 5 次?

【问题讨论】:

    标签: java spring-boot junit spring-async


    【解决方案1】:

    下面的线索是让子方法等待CountDownLatch。这样,所有线程将首先启动并在子例程中等待。

    然后,在测试方法内部,释放闩锁,让所有方法继续:

    @Test
    public void testAsync() {
            CountDownLatch waiter = new CountDownLatch(1);
            
            when(sub.run()).then((answer) -> {
                waiter.await();
                return;
            }
            
            Stream.generate(() -> new Thread(() -> service.processAsync()))
                    .limit(6)
                    .forEach(Thread::start);
    
            waiter.countDown(); //resumes all waiting threads
    }
    

    【讨论】:

      猜你喜欢
      • 2021-12-26
      • 2020-08-05
      • 1970-01-01
      • 2021-12-30
      • 1970-01-01
      • 2018-12-23
      • 2020-01-20
      • 2018-06-29
      • 2012-10-24
      相关资源
      最近更新 更多