我使用MockRestServiceServer
运行JUnit5,发现当我使用异步请求运行多个测试时,测试A中的MockRestServiceServer
将看到来自测试B的请求并标记为unexpected。
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
public class MyTestClass {
@Autowired
private RestTemplate restTemplate;
@Autowired
private WebApplicationContext wac;
private MockRestServiceServer mockServer;
private MockMvc mockMvc;
private URI asyncUri = URI.create("/asyncUrl");
@BeforeEach
public void setUp(){
mockerServer = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();
mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@AfterEach
public void tearDown(){
mockServer.verify();
mockServer.reset();
}
@Test
public void dontRunAsyncMethod(){
mockServer.reset(); // Added trying to fix the issue
mockServer.expect(ExpectedCount.never(), requestTo(asyncUri));
URI uri = URI.create("/myApi?runAsyncMethod=false");
mockMvc.perform(get(uri));
}
@Test
public void doRunAsyncMethod(){
mockServer.reset(); // Added trying to fix the issue
// Side issue here - I have to use `between` rather than `times`
// because mockServer validates before request happens
mockServer.expect(ExpectedCount.between(0, 1), requestTo(asyncUri));
URI uri = URI.create("/myApi?runAsyncMethod=true");
mockMvc.perform(get(uri));
}
}
当单独运行时,两个测试都通过了。但是,当我一起运行它们时,dontRunAsyncMethod
将失败,说没有请求被期望到/asyncUrl
。有没有一种方法可以更好地分离测试?我可以以某种方式确保在开始下一个测试之前所有请求都已完成?
1条答案
按热度按时间xqk2d5yq1#
你的评论本身提供了一个提示:
这实际上是个问题测试不会等待后台的异步调用。
首先,这个Assert应该被纠正为
times(1)
,因为它不会纠正异步调用在这个测试中被执行0次。通过允许它Assert调用可以被执行0次,异步行为的测试只是通过没有指定正确的行为。现在,这个测试在调用之前完成的事实(并且将在正确Assert
times(1)
时失败)与以下事实直接相关:如果两个测试都运行,则另一个测试无法Assert异步调用 not made。两者的原因都是异步测试没有等待异步调用异步发生:因此,调用在某个时刻在后台触发,但要等到一个测试完成并且JUnit转移到另一个测试。解决这个问题的方法应该是确保测试等待异步处理。希望类似这样的东西可以工作(假设
/myApi
实现中的异步机制与这里讨论的相同):(You我必须调整响应主体,如果响应状态不OK,则删除这些行或将其更改为预期状态。从文档中我不能立即清楚这些预期集合中的哪一组是指您正在测试的对
/myApi
的调用的响应,它引用了来自mockServer.expect(ExpectedCount.times(1), requestTo(asyncUri));
的响应-我在问题中没有看到/myApi
的实现,所以我在这里能做的最好的事情就是模仿文档。你也许可以查找asyncResult
的JavaDocs,看看是否有一个版本的响应体为空/没有响应体,如果你的回复根本就不应该有内容。)另外,如果您的 * nonasync * 测试导致进行异步调用,但是因为它没有等待最初不应该发生的异步进程,所以测试仍然通过了
never
调用的Assert,该怎么办?(并不是真正意义上的“永远”,而是在测试运行的时间内计数0次调用!)为了避免这种情况,我们还需要Assert该测试的请求没有运行异步活动:顺便说一句,你可以在每个测试开始时删除这些行(
@AfterEach
中的verify
和reset
不需要这些行):