I have a Spring Boot 1.4.2 application. Some code that is used during startup looks like this:
@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: ...
}
}
}
There is a component that determines the system type. This component is used during startup from other components. In production, everything works fine.
Now I want to add some integration tests using Spring 1.4's @MockBean
.
The test looks like this:
@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(){
// ...
}
}
Basically, the mocking works fine. My systemTypeDetectorMock is used and if I call getSystemType
-> TYPE_C
is returned.
The problem is that the application doesn't start. Currently springs working order seems to be:
- create all Mocks (without configuration all methods return null)
- start the application
- call
@Before
-methods (where the mocks would be configured) - start test
My problem is that the application starts with an uninitialized mock. So the call to getSystemType()
returns null.
My question is: How can I configure the mocks before application startup?
EDIT:
If somebody has the same problem, one workaround is to use @MockBean(answer = CALLS_REAL_METHODS)
. This calls the real component and in my case, the system starts up. After startup, I can change the mock behavior.