У меня есть приложение 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: ...
}
}
}
Есть компонент, который определяет тип системы. Этот компонент используется во время запуска из других компонентов. В производстве все работает отлично.
Теперь я хочу добавить несколько интеграционных тестов, используя 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(){
// ...
}
}
В основном издевательство работает отлично. Мой systemTypeDetectorMock используется, и если я вызываю getSystemType
→ TYPE_C
возвращается.
Проблема в том, что приложение не запускается. На данный момент рабочий порядок пружин вроде бы:
- создать все Mocks (без конфигурации все методы возвращают ноль)
- запустить приложение
- call @Before-методы (где будут настраиваться макеты)
- начать тест
Моя проблема в том, что приложение запускается с неинициализированным макетом. Таким образом, вызов getSystemType()
возвращает getSystemType()
.
Мой вопрос: как я могу настроить макеты перед запуском приложения?
Изменить: Если у кого-то есть такая же проблема, один из обходных путей должен использовать @MockBean(answer = CALLS_REAL_METHODS)
. Это вызывает реальный компонент, и в моем случае система запускается. После запуска я могу изменить макет поведения.