我正在测试一个Spring Boot应用程序。我有几个测试类,每个测试类都需要一组不同的模拟或其他定制的bean。
以下是设置草图:
的src /主/ 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 /测试/ 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定义的测试中,感觉它应该是一种干净的方式来执行此操作;唯一的缺点是这些嵌套配置最终会影响所有Spring TestContext测试,这些测试基于MyApplication(该组件扫描应用程序包)的配置。
如何修改我的设置,以便我仍然得到一个&#34;主要是真实的&#34;我的测试的Spring上下文,每个测试类中只有几个本地重写的bean?
答案 0 :(得分:11)
以下内容可以通过引入仅适用于当前测试类的新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);
}
}
}
答案 1 :(得分:3)
如果您有@SpringBootTest
,则只需使用@MockBean
注释要模拟的服务即可。就这么简单。
答案 2 :(得分:0)
我会做几件事:
@ComponentScan
。Component1TestWithFakeCommunication
中,将@SpringApplicationConfiguration(classes = MyApplication.class)
更改为@SpringApplicationConfiguration(classes = {MyApplication.class, Component1TestWithFakeCommunication.ContextConfiguration.class})
这应该为Spring提供足够的信息来模拟测试bean,但它应该阻止运行时ApplicationContext
注意到你的测试bean。