问题描述
我正在测试Spring Boot应用程序.我有几个测试类,每个测试类都需要一组不同的模拟或自定义的bean.
I am testing a Spring Boot application. I have several test classes, each of which needs a different set of mocked or otherwise customized beans.
这是设置的草图:
src/main/java:
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:
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.
The problem with the above setup is that the component scan configured in MyApplication picks up Component1TestWithFakeCommunication.ContextConfiguration, so I get a mock ServiceClient even in Component1TestWithRealCommunication where I want the real ServiceClient implementation.
尽管我可以使用@Autowired构造函数并在两个测试中自己构建组件,但是有很多东西需要复杂的设置,而我宁愿为我设置Spring TestContext(例如,Spring Data JPA存储库,应用程序外部库中的组件(这些组件从Spring上下文中提取bean等).在测试内部嵌套一个Spring配置,该配置可以在Spring上下文中局部覆盖某些Bean定义,这感觉应该是一种干净的方法.唯一的缺点是,这些嵌套配置最终会影响所有基于MyApplication(该组件会扫描应用程序包)的配置的Spring TestContext测试.
Although I could use @Autowired constructors and build up the components myself in both tests, there is a sufficient amount of stuff with complicated setup that I would rather have Spring TestContext set up for me (for example, Spring Data JPA repositories, components from libraries outside the app that pull beans from the Spring context, etc.). Nesting a Spring configuration inside the test that can locally override certain bean definitions within the Spring context feels like it should be a clean way to do this; the only downfall is that these nested configurations end up affecting all Spring TestContext tests that base their configuration on MyApplication (which component scans the app package).
如何修改设置,以便在每个测试类中只有几个本地覆盖的bean的情况下仍能为测试获得最真实的" Spring上下文?
How do I modify my setup so I still get a "mostly real" Spring context for my tests with just a few locally overridden beans in each test class?
推荐答案
以下内容应通过引入仅适用于当前测试类的新fake-communication
profile 来帮助您实现目标.
The following should help you to achieve your goal by introducing a new fake-communication
profile that is applicable only to the current test class.
@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);
}
}
}
这篇关于如何在SpringJunit4TestRunner中将@ComponentScan与测试特定的ContextConfiguration一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!