Модульное тестирование Spring: использование @SpyBean для макета пустого метода: получение исключения NullPointerException для этого компонента, если я не использую вместо него @Mock - PullRequest
0 голосов
/ 22 января 2020

Я пытаюсь заставить @SpyBean или @MockBean работать в этом тесте, так как они работают во всех других моих тестах. единственное отличие здесь в том, что этот тест использует активный профиль, потому что он высмеивает некоторые AWS libs

Мне не нужно создавать экземпляр этого класса, если я использую SpyBean, я видел бесчисленные примеры, похожие на мои ниже, которые похоже, работает нормально.

Тестируемый модуль:

@Component
public class SqsAdapter {

    @Autowired
    QueueMessagingTemplate queueMessagingTemplate;

    @Autowired
    MyProcessor processor;

    @SqsListener("${queue.name}")
    public void onEvent(String message) {
        if (!StringUtils.isEmpty(message)) {
            processor.process(message);
        } else { 
            log.error("Empty or null message received from queue");
        }
    }
}

и простой модульный тест, ожидающий вызова процесса (...):

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@ActiveProfiles("local")
public class SqsAdapterTest {

    @Autowired
    AmazonSQSAsync amazonSQS;

    @SpyBean
    MyProcessor processor;

    @InjectMocks
    SqsAdapter adapter;

    @Test
    public void testOnEvent() {
        doNothing().when(processor).process(any()); // <---- process() is void
        String event = "royale with cheese";
        adapter.onEvent(event);
        verify(processor, times(1)).process(event);
    }
}

когда я отлаживаю в модульном тесте, я получаю java.lang.NullPointerException на processor, как будто он никогда не инициализируется:

я также пытался переключить его на @MockBean с теми же результатами

Кроме того, я также попытался отменить тестирование @SpringBootTest и @ActiveProfiles ... и удалил зависимость AmazonSQSAsyn c, так как я не высмеиваю самого Слушателя, и он по-прежнему выдает тот же NPE

что мне здесь не хватает?

Ответы [ 2 ]

0 голосов
/ 23 января 2020

Думаю, я получил ответ: похоже, из-за смешивания фреймворков для тестирования путем смешивания аннотации @InjectMocks с @SpyBean ... поскольку я пытался не использовать mockito mocks, а это аннотация Mockito, я думаю, что это испортило тесты

тест рабочего модуля выглядит так:

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("local")
public class SqsAdapterTest {

    @Autowired
    AmazonSQSAsync amazonSQS;

    @SpyBean
    SeamEventProcessor seamEventProcessor;

    @Autowired
    SqsAdapter adapter;

    @Test
    public void testOnEvent() {
        doNothing().when(seamEventProcessor).process(any());
        String event = "royale with cheese";
        adapter.onEvent(event);
        verify(seamEventProcessor, times(1)).process(event);
    }
}
0 голосов
/ 22 января 2020

Я думаю, что Spring Boot Test не загружает бин MyProcessor в этой тестовой конфигурации.

Обычно, если боб загружен, аннотация @SpyBean может дать команду пружине обернуть исходный бин так, чтобы Вы получите шпион. Тем не менее, вы должны предоставить тестовую конфигурацию весенней загрузки таким образом, чтобы он обнаружил исходный компонент MyProcessor.

Если у вас есть класс конфигурации, укажите точку останова / log:


@Configuration
public class MyConfiguration {

    @Bean
    public MyProcessor myProcessor(...) {
       return new MyProcessor(); // <-- put breakpoint here and see whether its called at all
    }
}

В качестве альтернативы, если у вас есть что-то вроде:

@Component
public class MyProcessor {
    .... <-- put a breakpoint in constructor (create a default one if you don't have any)
}

Если мое предположение верно, теперь вы должны увидеть, что этот класс вообще не вызывается, и вы понимаете почему установка не делает работа.

Теперь вместо @SpringBootTest(classes = Application.class) попробуйте @SpringBootTest

Это попытается имитировать c процесс запуска приложения с весенней загрузкой с рекурсивным сканированием конфигураций и всего остального (это широкий topi c на самом деле вы должны прочитать документацию по тесту весенней загрузки).

Вместо того, что вы сделали, говорят Spring: «Я просто хочу работать с предопределенным классом конфигурации Application и все, не надо» не сканировать что-либо, не разрешать конфигурации, не разрешать бины, я знаю, что я делаю ".

После этого шага, если вы следовали соглашениям пакетов, предлагаемым sp При загрузке кольца вы должны увидеть, что оригинальный бин MyProcessor загружен и шпион создан

...