Mar*_*cel 22 java spring integration-testing mocking spring-boot
我有一个Spring Boot 1.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: ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
有一个组件可以确定系统类型.在从其他组件启动期间使用此组件.在生产中一切正常.
现在我想使用Spring 1.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(){
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
基本上嘲弄工作正常.我使用了systemTypeDetectorMock,如果我调用@MockBean
- > getSystemType
返回.
问题是应用程序无法启动.目前弹簧工作顺序似乎是:
我的问题是应用程序以未初始化的模拟开始.所以调用TYPE_C
返回null.
我的问题是:如何在应用程序启动之前配置模拟?
编辑:如果有人有同样的问题,一个解决方法是使用getSystemType()
.这称为真实组件,在我的情况下,系统启动.启动后我可以改变模拟行为.
Mac*_*iak 30
在这种情况下,您需要以我们在@MockBean
引入之前习惯的方式配置模拟- 通过手动指定一个@Primary
bean,该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);
}
}
Run Code Online (Sandbox Code Playgroud)
由于@TestConfiguration
class 是一个静态内部类,因此它只会被这个测试自动选择。您将放入的完整模拟行为@Before
必须移至初始化 bean 的方法。
lan*_*ava 16
我能够像这样修复它
@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();
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5286 次 |
最近记录: |