@SpringBootTest 和 @WebMvcTest 差在哪?为什么测试越写越慢?上下文缓存什么时候会失效?@MockitoBean 会让缓存失效吗?这篇用 JUnit Platform Console Launcher 把测试类跑一遍,数上下文的创建次数。
Plain(不启动 Spring):整条命令(含 JVM 启动)3 次中位 373 ms(范围 373~396);结果 tests successful 1, tests failed 0, containers failed 0
[Plain] 不启动 Spring:user-1
C6_Slice1(@WebMvcTest):整条命令(含 JVM 启动)3 次中位 1585 ms(范围 1541~1734);结果 tests successful 1, tests failed 0, containers failed 0
[C6_Slice1] Bean 定义 107 个,GET /users/1 → mocked
C1_Full1(@SpringBootTest + @AutoConfigureMockMvc):整条命令(含 JVM 启动)3 次中位 1647 ms(范围 1460~2015);结果 tests successful 1, tests failed 0, containers failed 0
[C1_Full1] Bean 定义 154 个,GET /users/1 → user-1不启动 Spring 最快;切片只有 Web 层的 Bean;完整上下文最大;这个小应用上切片和完整上下文耗时差别不大。
>> C1_Full1
(新建上下文 #1)
[C1_Full1] Bean 定义 154 个,GET /users/1 → user-1
>> C2_Full2
[C2_Full2] Bean 定义 154 个,GET /users/1 → user-1
>> C3_FullMock
(新建上下文 #2)
[C3_FullMock] Bean 定义 154 个,GET /users/1 → mocked
>> C4_FullProp
(新建上下文 #3)
[C4_FullProp] Bean 定义 154 个,GET /users/1 → user-1
>> C5_FullProfile
(新建上下文 #4)
[C5_FullProfile] Bean 定义 154 个,GET /users/1 → user-1
>> C6_Slice1
(新建上下文 #5)
[C6_Slice1] Bean 定义 107 个,GET /users/1 → mocked
>> C7_Slice2
[C7_Slice2] Bean 定义 107 个
>> C9_Dirties(2 个测试方法)
(新建上下文 #6)
[C9_Dirties.a] Bean 定义 146 个
(新建上下文 #7)
[C9_Dirties.b] Bean 定义 146 个
整个 JVM 里 UserController 一共被创建了 7 次(= 创建的 Spring 上下文个数)
结果 tests successful 9, tests failed 0, containers failed 0,整条命令 2309 ms配置相同则共用;@MockitoBean、@TestPropertySource、@ActiveProfiles、@DirtiesContext 都会导致新建上下文。
退出码 1;tests successful 0, tests failed 1, containers failed 0
=> java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration@388623ad testClass = demo.C8_SliceNoMock, locations = [], classes = [demo.App], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.webmvc
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userController' defined in file [<jtmp>/x82/out/demo/UserController.class]: Unsatisfied dependency expressed through constructor parameter 0: No qualifying bean of type 'demo.UserService' available: expected at least 1 bea
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'demo.UserService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}@WebMvcTest 不加载 @Service,缺少的依赖要用 @MockitoBean 补上,否则上下文启动失败。