我有一个SpringBoot1.4.2应用程序。在启动期间使用的一些代码如下所示:
@Component
class SystemTypeDetector{
public enum SystemType{ TYPE_A, TYPE_B, TYPE_C }
public SystemType getSystemType(){ return ... }
}
@Component
public class SomeOtherComponent{
@Autowired
private SystemTypeDetector systemTypeDetector;
@PostConstruct
public void startup(){
switch(systemTypeDetector.getSystemType()){ // <-- NPE here in test
case TYPE_A: ...
case TYPE_B: ...
case TYPE_C: ...
}
}
}
有一个组件决定系统类型。此组件在从其他组件启动时使用。在生产中一切都很好。
现在,我想使用Spring1.4的@MockBean
添加一些集成测试。
测试结果如下:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyWebApplication.class, webEnvironment = RANDOM_PORT)
public class IntegrationTestNrOne {
@MockBean
private SystemTypeDetector systemTypeDetectorMock;
@Before
public void initMock(){
Mockito.when(systemTypeDetectorMock.getSystemType()).thenReturn(TYPE_C);
}
@Test
public void testNrOne(){
// ...
}
}
基本上,嘲弄的效果很好。使用我的systemTypeDetectorMock,如果我调用getSystemType
,则返回-> TYPE_C
。
问题是应用程序没有启动。目前弹簧的工作顺序似乎是:
我的问题是,应用程序以未初始化的模拟开始。因此,对getSystemType()
的调用返回null。
我的问题是:如何在应用程序启动之前配置模拟?
编辑:,如果某人有同样的问题,一个解决办法就是使用@MockBean(answer = CALLS_REAL_METHODS)
。这就调用了真正的组件,在我的例子中,系统启动了。启动后,我可以更改模拟行为。
发布于 2019-10-23 07:09:37
在本例中,您需要以我们在引入@MockBean
之前使用的方式配置模拟--通过手动指定一个@Primary
bean来替换上下文中的原始bean。
@SpringBootTest
class DemoApplicationTests {
@TestConfiguration
public static class TestConfig {
@Bean
@Primary
public SystemTypeDetector mockSystemTypeDetector() {
SystemTypeDetector std = mock(SystemTypeDetector.class);
when(std.getSystemType()).thenReturn(TYPE_C);
return std;
}
}
@Autowired
private SystemTypeDetector systemTypeDetector;
@Test
void contextLoads() {
assertThat(systemTypeDetector.getSystemType()).isEqualTo(TYPE_C);
}
}
因为@TestConfiguration
类是一个静态的内部类,所以只有通过这个测试才会自动选择它。必须将要放入@Before
中的完整模拟行为移到初始化bean的方法中。
发布于 2021-05-20 11:30:15
我就这样修好了
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyWebApplication.class, webEnvironment = RANDOM_PORT)
public class IntegrationTestNrOne {
// this inner class must be static!
@TestConfiguration
public static class EarlyConfiguration {
@MockBean
private SystemTypeDetector systemTypeDetectorMock;
@PostConstruct
public void initMock(){
Mockito.when(systemTypeDetectorMock.getSystemType()).thenReturn(TYPE_C);
}
}
// here we can inject the bean created by EarlyConfiguration
@Autowired
private SystemTypeDetector systemTypeDetectorMock;
@Autowired
private SomeOtherComponent someOtherComponent;
@Test
public void testNrOne(){
someOtherComponent.doStuff();
}
}
发布于 2020-09-09 14:02:18
您可以使用以下技巧:
@Configuration
public class Config {
@Bean
public BeanA beanA() {
return new BeanA();
}
@Bean
public BeanB beanB() {
return new BeanB(beanA());
}
}
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {TestConfig.class, Config.class})
public class ConfigTest {
@Configuration
static class TestConfig {
@MockBean
BeanA beanA;
@PostConstruct
void setUp() {
when(beanA.someMethod()).thenReturn(...);
}
}
}
至少它适用于spring-boot-2.1.9.RELEASE
https://stackoverflow.com/questions/40563409
复制相似问题