Jest并发执行测试时搭配MSW是否会存在竞态条件?
结论
你担心的跨测试文件MSW处理器竞态串扰问题,在Jest默认配置下不会发生,不需要为了规避这个问题加--runInBand参数串行执行测试。
核心原因
Jest默认的多测试文件并发能力是基于Node.js worker_threads 实现的线程级隔离:
- 每个测试文件运行在独立的工作线程中,线程间内存完全隔离,不存在共享全局变量
- 你在
setupTests.js中初始化的MSW server实例、jsdom模拟环境,都会在每个工作线程里独立创建一份,不同测试文件操作的根本不是同一个server对象,自然不会出现A文件追加的接口处理器被B文件调用的情况。
官方推荐
afterEach重置逻辑的真实作用 这个重置操作不是为了解决跨文件并发问题,是为了规避同一个测试文件内的用例互相污染:
- 同一个测试文件内的所有
test/it用例,共享当前线程内的同一个MSW server实例 - 如果你在某个用例里通过
server.use()追加了运行时的请求处理器,测试结束后不重置的话,这个处理器会一直存在,影响同文件内后续执行的其他用例 - 比如你在第一个用例里给user接口加了返回
{firstName: 'Paul'}的mock,跑完没重置,第二个用例本来想自己加返回{firstName: 'Ringo'}的mock,就会被前面遗留的处理器拦截,导致断言失败
官方推荐的配置代码如下,只需要在setupTests.js加一次即可:
// 重置测试过程中追加的请求处理器,避免同文件内用例互相影响 afterEach(() => server.resetHandlers())
真正可能出现MSW竞态的场景
只有两种非常规场景会碰到你担心的串扰问题:
- 你在同一个测试文件内使用了
test.concurrent()API写并发用例,这些用例跑在同一个线程里,共享同一个server实例,追加处理器时会出现竞争 - 你自定义修改了Jest的调度配置,强制让多个测试文件跑在同一个工作线程中(常规项目不会做这种配置)
关于jsdom的同类疑问
这个担心同样多余:每个工作线程里的jsdom环境是独立初始化的,你在A测试文件里操作的document、挂载的DOM节点、注册的全局事件,都不会泄漏到B测试文件的jsdom实例中。你需要关注的只有同文件内的DOM污染,这也是Testing Library等工具默认推荐在afterEach中执行DOM清理的原因。
--runInBand会关闭多线程并发,大幅降低测试运行速度,只有当你碰到明确的跨文件mock污染问题时,再用它做问题排查即可,常规项目不需要为了MSW特意开启串行执行。
内容的提问来源于stack exchange,提问作者Bill Keese
相关产品推荐
相关产品推荐

