Curse of spring boot test
-
Upload
- -
Category
Technology
-
view
237 -
download
0
Transcript of Curse of spring boot test
ТестируемВместе со Spring Boot Test
@tolkv
@lavcraft
@jekaborisov
@jeka1978
В программеТестирование живого приложения● Старые подходы
○ @ContextConfiguration○ @ContextHierarchy && @DirtiesContext○ @ActiveProfiles
● Что нового нам приготовил Spring Boot?○ @SpringBootTest○ @TestConfiguration○ @MockBean && @SpyBean && @*Beans○ @DataJpaTest○ @WebMvcTest
● Кэширование spring контекстов● Шкала тестов
Шкала Тестов
UnitComponent Test
Microservice TestSystem Test
➯ ➯➯ ➯
ДаноЧат поддержки разработчиков
assistant
yegor256-assistant
jbaruch-assistant
Queue
мыweb
rest
rest
rest
Default AnswersDatabase
Эксперты
ДаноЧат поддержки разработчиков
assistant
yegor256-assistant
jbaruch-assistant
Queue
мыweb
rest
rest
rest
Default AnswersDatabase
Demo
А давайте тестировать
А давайте тестировать
У кого спросить? [yegor256/jbaruch]
router
yegor256-assistant
jbaruch-assistant
Default AnswersDatabase
Yegor256 Resolver$tokens.yegor256
JBaruch Resolver
...
$tokens.jbaruch
А давайте тестировать. Тест #11. Пишем Egor256WordsFrequencyResolverTest.
Demo
А давайте тестировать. Тест #11. Пишем Egor256WordsFrequencyResolverTest.2. Как ни крути, но нужен более “интеграционный тест”
Шкала Тестов
Unit
➯
Шкала Тестов
UnitComponent Test
➯ ➯
Demo
1. Пишем TextBasedQuestionTypeResolverTest
А давайте тестировать. Тест #2
Шкала Тестов
UnitComponent Test
➯ ➯
1. Пишем TextBasedQuestionTypeResolverTest2. Вручную создаем три бина для тестирования
TextBasedQuestionTypeResolver на примере Барух vs Егор кейса
А давайте тестировать. Тест #2
Demo
1. Пишем TextBasedQuestionTypeResolverTest2. Вручную создаем три бина для тестирования
TextBasedQuestionTypeResolver на примере Барух vs Егор кейса3. Все падает потому что не подтягивается application.yml4. @PropertySource …
А давайте тестировать. Тест #2
@SpringApplicationConfiguration(classes = ....class, initializers = YamlFileApplicationContextInitializer.class)public class OurTest { @Test public test(){... }}
А давайте тестировать. Тест #2
Spring Boot обновки
1. @SpringBootTest2. @TestConfiguration3. @MockBean && @SpyBean4. @DataJpaTest5. @MockMvcTest
Углубляемся в Spring. Тест #21. Применяем @SpringBootTest
Demo
Углубляемся в Spring. Тест #21. Применяем @SpringBootTest2. Долго…3. @SpringBootTest(classes = ...class)
Углубляемся в Spring. Тест #21. Применяем @SpringBootTest2. Долго…3. @SpringBootTest(classes = ...class)4. Стало быстрее
Углубляемся в Spring. Тест #21. Применяем @SpringBootTest2. Долго…3. @SpringBootTest(classes = ...class)4. Стало быстрее5. С кэшированием конфигураций – еще быстрее
Углубляемся в Spring. Тест #2@ContextHierarchy({ @ContextConfiguration(classes=WordsCommonConfiguration.class), @ContextConfiguration(classes= ...class)})
Demo
Углубляемся в Spring. Тест #2@ContextHierarchy({ @ContextConfiguration(classes=WordsCommonConfiguration.class), @ContextConfiguration(classes=....class)})
Порядок важен! Т.к другая конфигурация использует бины из WordsCommonConfiguration
Но ничего не закешировалось. Тест #2
Но ничего не закешировалось. Тест #2
@SpringBootTest – должен быть везде
Но ничего не закешировалось. Тест #2
@SpringBootTest – должен быть везде@Import – должен быть нигде
Но ничего не закешировалось. Тест #2
@SpringBootTest – должен быть везде@Import – должен быть нигде@ActiveProfiles – один на всех
Но ничего не закешировалось. Тест #2
@SpringBootTest – должен быть везде@Import – должен быть нигде@ActiveProfiles – один на всехSpringBootTest.properties – должны быть одинаковые
Но ничего не закешировалось. Тест #2
@SpringBootTest – должен быть везде@Import – должен быть нигде@ActiveProfiles – один на всехSpringBootTest.properties – должны быть одинаковые
Порядок важен!Любая перестановка – cache miss
Но ничего не закешировалось. Тест #2
@SpringBootTest(properties={"a=b","b=a"})@SpringBootTest(properties={"b=a","a=b"})
Но ничего не закешировалось. Тест #2
@SpringBootTest(properties={"a=b","b=a"})@SpringBootTest(properties={"b=a","a=b"})
Кэш не сработает
Но ничего не закешировалось. Тест #2
@SpringBootTest – должен быть везде@Import – должен быть нигде@ActiveProfiles – один на всехSpringBootTest.properties – должны быть одинаковые
Хрупкий кэш
Все может привести к потере кэша
Пользуемся силойlogging.level.org.springframework.test.context.cache=debug
Б – безопасность@SpringBootTest@ActiveProfiles("yegor_vs_jbaruch")public abstract class ResolversAbstractCommonConfiguration {
}
А если наоборот?
А если наоборот?@DirtiesContext(...)
А если наоборот?@DirtiesContext(...)
methodMode() default MethodMode.AFTER_METHODclassMode() default ClassMode.AFTER_CLASS...
Проверим наши знания. Тест #31. протестируем AnswerCacheServiceJPABackend
Spring Boot обновки
1. @SpringBootTest2. @MockBean && @SpyBean3. @TestConfiguration4. @DataJpaTest5. @MockMvcTest
Синергия с Mockito1. @MockBean/@SpyBean2. @PostConstruct для настройки3. @Bean для настройки конкретных моков
1. Запустим все тесты
Все ли хорошо?
1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает
Все ли хорошо?
1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает3. Загрузил бины из другого теста!
Все ли хорошо?
Spring Boot обновки
1. @SpringBootTest2. @MockBean && @SpyBean3. @TestConfiguration4. @DataJpaTest5. @MockMvcTest
1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает3. Загрузил бины из другого теста!4. @TestConfiguration!
Все ли хорошо?
1. Не сканируется @SpringBootTest2. Не сканируется другими конфигурациями и тестами3. Не прерывает процесс сканирования @SpringBootTest
@TestConfiguration
1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает3. Загрузил бины из другого теста!4. @TestConfiguration!5. DeveloperAssistantApplicationTests.contextLoad работает
Все ли хорошо?
1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает3. Загрузил бины из другого теста!4. @TestConfiguration!5. DeveloperAssistantApplicationTests.contextLoad работает6. А AnswerCacheServiceJPABackendTest перестал7. Загрузил бины из другого теста!
Все ли хорошо?
1.
Как @SpringBootTest сканирует пакеты
Два процесса сканирования1. @SpringBootTest сканирование2. @SpringBootApplication (@ComponentScan)
Два процесса сканирования1. @SpringBootTest сканирование2. @SpringBootApplication (@ComponentScan)
Вверх
Два процесса сканирования1. @SpringBootTest сканирование2. @SpringBootApplication (@ComponentScan) Вниз
Вверх
@SpringBootTest
Два процесса сканирования
@SpringBootTest
Два процесса сканирования
@SpringBootTest
Два процесса сканирования
Два процесса сканирования
@SpringBootTest
Два процесса сканирования
@SpringBootTest
test classpath extends main classpath
Два процесса сканирования
@SpringBootTest
@SpringBootApplication
src/main будет так же просканирован*
test classpath extends main classpath
Два процесса сканирования
@SpringBootTest
@SpringBootApplication
src/main будет так же просканирован*
test classpath extends main classpath
Два процесса сканирования
@SpringBootTest
@SpringBootApplication
src/main будет так же просканирован*
test classpath extends main classpath
Два процесса сканирования
@SpringBootTest
@SpringBootApplication
src/main будет так же просканирован*
test classpath extends main classpath
Два процесса сканирования
@SpringBootTest
@SpringBootApplication
src/main будет так же просканирован*
test classpath extends main classpath
Тоже и сsrc/main/**
1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает3. Загрузил бины из другого теста!4. @TestConfiguration!5. DeveloperAssistantApplicationTests.contextLoad работает6. А AnswerCacheServiceJPABackendTest перестал7. Загрузил бины из другого теста!8. @SpringBootConfiguration остановит сканирование
Все ли хорошо?
@SpringBootConfigurationpublic class StopConfiguration {
}
Чиним
Component Tests
Spring Boot обновки
1. @SpringBootTest2. @TestConfiguration3. @MockBean && @SpyBean4. @DataJpaTest5. @MockMvcTest
@DataJpaTest
1. сканирует все репозитории
@DataJpaTest
1. сканирует все репозитории2. конфигурирует EntityManager3. загружает другие конфигурации
1. сканирует все репозитории2. конфигурирует EntityManager3. загружает другие конфигурации4. фильтрует все не относящееся к Data/JPA
Применим знания
@DataJpaTest
Тестируем DefaultAssistantJpaBackendTest1. @DataJpaTest не загружает компоненты Spring
Тестируем DefaultAssistantJpaBackendTest1. @DataJpaTest не загружает компоненты Spring2. Делаем конфигурацию, загружаем недостающее
Тестируем DefaultAssistantJpaBackendTest1. @DataJpaTest не загружает компоненты Spring2. Делаем конфигурацию, загружаем недостающее3. Ничего не работает, из за @SpringBootConfiguration
Тестируем DefaultAssistantJpaBackendTest1. @DataJpaTest не загружает компоненты Spring2. Делаем конфигурацию, загружаем недостающее3. Ничего не работает, из за @SpringBootConfiguration4. Переносим в новый package – все @*Test тесты должны быть
изолированы
@WebMvcTest
1. Не грузит компоненты спринга
@WebMvcTest
1. Не грузит компоненты спринга2. Грузит только то что относится к Web
@WebMvcTest
1. Не грузит компоненты спринга2. Грузит только то что относится к Web3. Сразу изолируем в отдельный пакет
Получаем суперспособность:
@AutowiredMockMvc mockMvc;
Где настраивать @MockBean1. В @*Configuration –
если мок нужен на этапе создания контекста2. В тесте (@Before/setup/etc)
если мок нужен только на этапе выполнения теста
Что же делает @SpringBootTest1. Без classes
a. сканирует со своего пакета “вверх” в поисках @SpringBootConfigurationi. игнорирует остальных
b. падает если не находит или находит несколько в одном пакете
2. classes=~@Configurationa. поднимет только указанные конфигурации
3. classes=~@TestConfigurationa. поднимет указанный контекст и продолжит сканирование. см пункт 1
Зачем нужен @SpringBootTest1. Полный тест на весь контекст2. Изменение properties3. Тесты с определенным скоупом – пакет/конфигурация/автоскан
Зачем нужен @TestConfiguration1. Если нужно не прерывать сканирование @SpringBootTest2. Изолированные тесты (игнорируется при сканировании)
Зачем нужен @SpringBootConfiguration1. Прерывать сканирование инициированное @SpringBootTest
Выводы1. Spring для Unit тестирования может быть быстрым
Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука
Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука3. Для тестов – только @TestConfiguration
Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука3. Для тестов – только @TestConfiguration4. Изолировать группы тестов с помощью
Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука3. Для тестов – только @TestConfiguration4. Изолировать группы тестов с помощью
a. выделения в пакетыb. @SpringBootConfiguration
Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука3. Для тестов – только @TestConfiguration4. Изолировать группы тестов с помощью
a. выделения в пакеты (особенно для @*Test)b. @SpringBootConfiguration
5. SpringBootTest надо в основном использоватьдля микросервис тестов
Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука3. Для тестов – только @TestConfiguration4. Изолировать группы тестов с помощью
a. выделения в пакетыb. @SpringBootConfiguration
5. SpringBootTest надо в основном использоватьдля микросервис тестов
6. Если есть DirtiesContext – стоит задуматься :)
Шкала Тестов
UnitComponent Test
Microservice TestSystem Test
➯ ➯➯ ➯ Следующий доклад
Unit Component Microservice
Что нужно Junit/Mockito @ContextConfiguration @SpringBootTest
Кто управляет new Spring Spring Boot
QA
105
1. @ComponentScan > @TestConfiguration > @Configuratin! @ComponentScan находит даже @TestConfiguration
2. @DataJpaTest > @SpringBootTest3. @DataJpaTest и @WebMvcTest должны быть в отдельных пакетах
Если есть сомнения – смотри автора! Juergen Hoeller*
Дополнительно