SpringBootTest - 如何在运行时配置中替换一个 bean?
SpringBootTest - how to replace one bean in runtime configuration?
我正在为 Spring 引导应用程序编写集成测试。只要我使用 100% 的运行时配置进行测试,一切都会顺利进行。但是当我试图为 bean 提供一个自定义 bean 时,一切都崩溃了。
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CombinedControllerIntegrationTest2 {
@TestConfiguration
static class ContextConfiguration {
@Bean
@Primary
public SolrDocumentTypeMapRepository solrDocumentTypeMapRepository() {
LOG.debug("SolrDocumentTypeMapRepository is being initialized.");
// etc.
上面的代码变体导致加载真实的运行时 SolrDocumentTypeMapRepository。我的测试 class 中的 ContextConfiguration 被忽略。
如果我尝试在我的内部 ContextConfiguration 上使用 @Configuration 而不是 @TestConfiguration,执行会落入另一个极端 - 它以
结束
org.springframework.context.ApplicationContextException: Unable to
start EmbeddedWebApplicationContext due to missing
EmbeddedServletContainerFactory bean.
因为显然没有加载其余配置。
如果我尝试把
@ContextConfiguration(classes =
{CombinedControllerIntegrationTest2.ContextConfiguration.class,GatewayApplication.class})
在我的主要测试 class 中,它以与 #1 相同的方式失败 - 即我的 ContextConfiguration 被忽略。
有什么想法吗?
P.S。我知道我可以使用@MockBean(这甚至在其他情况下也有效),但是在这里,因为在某些时候我依赖于主代码中的@PostConsruct 方法,@MockBeans 是无用的。
不使用@Runwith(SpringJunit4Classrunner.class),而是使用@RunWith(SpringRunner.class)。这应该可以帮助您解决错误。
用一个 Bean 进行单元测试
只需使用 @RunWith(SpringRunner.class)
注释,它应该可以工作。您也可以使用 @RunWith(SpringJUnit4ClassRunner.class)
。两者都应该有效。
请不要使用 @SpringBootTest
注解。它将连接整个应用程序。
这是您更新后的示例,
@RunWith(SpringRunner.class)
public class CombinedControllerIntegrationTest2 {
@TestConfiguration
static class ContextConfiguration {
@Bean
public SolrDocumentTypeMapRepository solrDocumentTypeMapRepository() {
LOG.debug("SolrDocumentTypeMapRepository is being initialized.");
return new SolrDocumentTypeMapRepository(...);
}
}
@Autowired
private SolrDocumentTypeMapRepository repository;
@Test
public void test() {
assertNotNull(repository);
}
}
使用替换的 Bean 进行集成测试
创建一个新的测试Spring启动应用程序。它应该排除负责创建 SolrDocumentTypeMapRepository
bean 的配置 class(例如 SolrConfiguration
)。
@SpringBootApplication
@ComponentScan(basePackages = {
"com.abc.pkg1",
"com.abc.pk2"},
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
value = SolrConfiguration.class)})
public class TestApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(TestApplication.class, args);
}
}
现在,在测试 class 中使用 @ContextConfiguration
注释来添加 TestApplication.class
和 ContextConfiguration.class
。这会将您的应用程序与所有必需的 bean 连接起来,包括被替换的 bean。下面显示的是更新后的测试 class,
@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment =
SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = {TestApplication.class,
CombinedControllerIntegrationTest2.ContextConfiguration.class})
public class CombinedControllerIntegrationTest2 {
@TestConfiguration
static class ContextConfiguration {
@Bean
public SolrDocumentTypeMapRepository solrDocumentTypeMapRepository() {
LOG.debug("SolrDocumentTypeMapRepository is being initialized.");
return new SolrDocumentTypeMapRepository(...);
}
}
...
}
使用@Mockean 模拟您的存储库。并在测试中添加行为:
@SpringBootTest
@AutoConfigureMockMvc
@RunWith(SpringRunner.class)
public abstract class IntegrationTest {
@MockBean
SolrDocumentTypeMapRepository solrDocumentTypeMapRepository;
@Test
public void mySuperTest(){
Mockito.when(solrDocumentTypeMapRepository.getById(Mockito.any())).thenReturn(someInstance);
Assert.assertEquals(solrDocumentTypeMapRepository.getById("someId"), someInstance);
}
}
我正在为 Spring 引导应用程序编写集成测试。只要我使用 100% 的运行时配置进行测试,一切都会顺利进行。但是当我试图为 bean 提供一个自定义 bean 时,一切都崩溃了。
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CombinedControllerIntegrationTest2 {
@TestConfiguration
static class ContextConfiguration {
@Bean
@Primary
public SolrDocumentTypeMapRepository solrDocumentTypeMapRepository() {
LOG.debug("SolrDocumentTypeMapRepository is being initialized.");
// etc.
上面的代码变体导致加载真实的运行时 SolrDocumentTypeMapRepository。我的测试 class 中的 ContextConfiguration 被忽略。
如果我尝试在我的内部 ContextConfiguration 上使用 @Configuration 而不是 @TestConfiguration,执行会落入另一个极端 - 它以
结束org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
因为显然没有加载其余配置。
如果我尝试把
@ContextConfiguration(classes = {CombinedControllerIntegrationTest2.ContextConfiguration.class,GatewayApplication.class})
在我的主要测试 class 中,它以与 #1 相同的方式失败 - 即我的 ContextConfiguration 被忽略。
有什么想法吗?
P.S。我知道我可以使用@MockBean(这甚至在其他情况下也有效),但是在这里,因为在某些时候我依赖于主代码中的@PostConsruct 方法,@MockBeans 是无用的。
不使用@Runwith(SpringJunit4Classrunner.class),而是使用@RunWith(SpringRunner.class)。这应该可以帮助您解决错误。
用一个 Bean 进行单元测试
只需使用 @RunWith(SpringRunner.class)
注释,它应该可以工作。您也可以使用 @RunWith(SpringJUnit4ClassRunner.class)
。两者都应该有效。
请不要使用 @SpringBootTest
注解。它将连接整个应用程序。
这是您更新后的示例,
@RunWith(SpringRunner.class)
public class CombinedControllerIntegrationTest2 {
@TestConfiguration
static class ContextConfiguration {
@Bean
public SolrDocumentTypeMapRepository solrDocumentTypeMapRepository() {
LOG.debug("SolrDocumentTypeMapRepository is being initialized.");
return new SolrDocumentTypeMapRepository(...);
}
}
@Autowired
private SolrDocumentTypeMapRepository repository;
@Test
public void test() {
assertNotNull(repository);
}
}
使用替换的 Bean 进行集成测试
创建一个新的测试Spring启动应用程序。它应该排除负责创建
SolrDocumentTypeMapRepository
bean 的配置 class(例如SolrConfiguration
)。@SpringBootApplication @ComponentScan(basePackages = { "com.abc.pkg1", "com.abc.pk2"}, excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = SolrConfiguration.class)}) public class TestApplication { public static void main(String[] args) throws Exception { SpringApplication.run(TestApplication.class, args); } }
现在,在测试 class 中使用
@ContextConfiguration
注释来添加TestApplication.class
和ContextConfiguration.class
。这会将您的应用程序与所有必需的 bean 连接起来,包括被替换的 bean。下面显示的是更新后的测试 class,@ActiveProfiles("test") @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration(classes = {TestApplication.class, CombinedControllerIntegrationTest2.ContextConfiguration.class}) public class CombinedControllerIntegrationTest2 { @TestConfiguration static class ContextConfiguration { @Bean public SolrDocumentTypeMapRepository solrDocumentTypeMapRepository() { LOG.debug("SolrDocumentTypeMapRepository is being initialized."); return new SolrDocumentTypeMapRepository(...); } } ... }
使用@Mockean 模拟您的存储库。并在测试中添加行为:
@SpringBootTest
@AutoConfigureMockMvc
@RunWith(SpringRunner.class)
public abstract class IntegrationTest {
@MockBean
SolrDocumentTypeMapRepository solrDocumentTypeMapRepository;
@Test
public void mySuperTest(){
Mockito.when(solrDocumentTypeMapRepository.getById(Mockito.any())).thenReturn(someInstance);
Assert.assertEquals(solrDocumentTypeMapRepository.getById("someId"), someInstance);
}
}