我正在测试一个Spring Boot应用程序。我有几个测试类,每个测试类都需要一组不同的模拟或自定义的bean。
这是设置的草图:
src / main / java:
package com.example.myapp; @SpringBootApplication @ComponentScan( basePackageClasses = { MyApplication.class, ImportantConfigurationFromSomeLibrary.class, ImportantConfigurationFromAnotherLibrary.class}) @EnableFeignClients @EnableHystrix public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } } package com.example.myapp.feature1; @Component public class Component1 { @Autowired ServiceClient serviceClient; @Autowired SpringDataJpaRepository dbRepository; @Autowired ThingFromSomeLibrary importantThingIDontWantToExplicitlyConstructInTests; // methods I want to test... }
src / test / java:
package com.example.myapp; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = MyApplication.class) @WebAppConfiguration @ActiveProfiles("test") public class Component1TestWithFakeCommunication { @Autowired Component1 component1; // <-- the thing we're testing. wants the above mock implementations of beans wired into it. @Autowired ServiceClient mockedServiceClient; @Configuration static class ContextConfiguration { @Bean @Primary public ServiceClient mockedServiceClient() { return mock(ServiceClient.class); } } @Before public void setup() { reset(mockedServiceClient); } @Test public void shouldBehaveACertainWay() { // customize mock, call component methods, assert results... } } package com.example.myapp; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = MyApplication.class) @WebAppConfiguration @ActiveProfiles("test") public class Component1TestWithRealCommunication { @Autowired Component1 component1; // <-- the thing we're testing. wants the real implementations in this test. @Autowired ServiceClient mockedServiceClient; @Before public void setup() { reset(mockedServiceClient); } @Test public void shouldBehaveACertainWay() { // call component methods, assert results... } }
上面的设置的问题是,在MyApplication中配置的组件扫描拾取了Component1TestWithFakeCommunication.ContextConfiguration,因此,即使在Component1TestWithRealCommunication中,我也想要一个真实的ServiceClient来模拟ServiceClient。
尽管我可以使用@Autowired构造函数并在两个测试中自己构建组件,但是有足够多的东西具有复杂的设置,而我宁愿为我设置Spring TestContext(例如,Spring Data JPA存储库,库中的组件)在应用程序外部从Spring上下文中提取bean等)。在测试内部嵌套一个Spring配置,该配置可以在Spring上下文中局部覆盖某些Bean定义,这似乎是一种干净的方法。唯一的不足是,这些嵌套配置最终会影响所有基于MyApplication(该组件会扫描应用程序包)的配置的Spring TestContext测试。
如何修改我的设置,以便在每个测试类中只有几个本地重写的bean的情况下仍然为测试提供“最真实的” Spring上下文?
以下内容将通过引入一个仅适用于当前测试类的新fake-communication 配置文件 来帮助您实现目标。
fake-communication
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = MyApplication.class) @WebAppConfiguration @ActiveProfiles({"test", "fake-communication"}) public class Component1TestWithFakeCommunication { // @Autowired ... @Profile("fake-communication") @Configuration static class ContextConfiguration { @Bean @Primary public ServiceClient mockedServiceClient() { return mock(ServiceClient.class); } } }