Curse of spring boot test

106
Тестируем Вместе со Spring Boot Test

Transcript of Curse of spring boot test

Page 1: Curse of spring boot test

ТестируемВместе со Spring Boot Test

Page 2: Curse of spring boot test

@tolkv

@lavcraft

Page 3: Curse of spring boot test

@jekaborisov

@jeka1978

Page 4: Curse of spring boot test

В программеТестирование живого приложения● Старые подходы

○ @ContextConfiguration○ @ContextHierarchy && @DirtiesContext○ @ActiveProfiles

● Что нового нам приготовил Spring Boot?○ @SpringBootTest○ @TestConfiguration○ @MockBean && @SpyBean && @*Beans○ @DataJpaTest○ @WebMvcTest

● Кэширование spring контекстов● Шкала тестов

Page 5: Curse of spring boot test

Шкала Тестов

UnitComponent Test

Microservice TestSystem Test

➯ ➯➯ ➯

Page 6: Curse of spring boot test

ДаноЧат поддержки разработчиков

assistant

yegor256-assistant

jbaruch-assistant

Queue

мыweb

rest

rest

rest

Default AnswersDatabase

Page 7: Curse of spring boot test

Эксперты

Page 8: Curse of spring boot test

ДаноЧат поддержки разработчиков

assistant

yegor256-assistant

jbaruch-assistant

Queue

мыweb

rest

rest

rest

Default AnswersDatabase

Page 9: Curse of spring boot test

Demo

Page 10: Curse of spring boot test

А давайте тестировать

Page 11: Curse of spring boot test

А давайте тестировать

У кого спросить? [yegor256/jbaruch]

router

yegor256-assistant

jbaruch-assistant

Default AnswersDatabase

Yegor256 Resolver$tokens.yegor256

JBaruch Resolver

...

$tokens.jbaruch

Page 12: Curse of spring boot test

А давайте тестировать. Тест #11. Пишем Egor256WordsFrequencyResolverTest.

Page 13: Curse of spring boot test

Demo

Page 14: Curse of spring boot test

А давайте тестировать. Тест #11. Пишем Egor256WordsFrequencyResolverTest.2. Как ни крути, но нужен более “интеграционный тест”

Page 15: Curse of spring boot test

Шкала Тестов

Unit

Page 16: Curse of spring boot test

Шкала Тестов

UnitComponent Test

➯ ➯

Page 17: Curse of spring boot test

Demo

Page 18: Curse of spring boot test

1. Пишем TextBasedQuestionTypeResolverTest

А давайте тестировать. Тест #2

Page 19: Curse of spring boot test

Шкала Тестов

UnitComponent Test

➯ ➯

Page 20: Curse of spring boot test

1. Пишем TextBasedQuestionTypeResolverTest2. Вручную создаем три бина для тестирования

TextBasedQuestionTypeResolver на примере Барух vs Егор кейса

А давайте тестировать. Тест #2

Page 21: Curse of spring boot test

Demo

Page 22: Curse of spring boot test

1. Пишем TextBasedQuestionTypeResolverTest2. Вручную создаем три бина для тестирования

TextBasedQuestionTypeResolver на примере Барух vs Егор кейса3. Все падает потому что не подтягивается application.yml4. @PropertySource …

А давайте тестировать. Тест #2

Page 23: Curse of spring boot test

@SpringApplicationConfiguration(classes = ....class, initializers = YamlFileApplicationContextInitializer.class)public class OurTest { @Test public test(){... }}

А давайте тестировать. Тест #2

Page 24: Curse of spring boot test

Spring Boot обновки

1. @SpringBootTest2. @TestConfiguration3. @MockBean && @SpyBean4. @DataJpaTest5. @MockMvcTest

Page 25: Curse of spring boot test

Углубляемся в Spring. Тест #21. Применяем @SpringBootTest

Page 26: Curse of spring boot test

Demo

Page 27: Curse of spring boot test

Углубляемся в Spring. Тест #21. Применяем @SpringBootTest2. Долго…3. @SpringBootTest(classes = ...class)

Page 28: Curse of spring boot test

Углубляемся в Spring. Тест #21. Применяем @SpringBootTest2. Долго…3. @SpringBootTest(classes = ...class)4. Стало быстрее

Page 29: Curse of spring boot test

Углубляемся в Spring. Тест #21. Применяем @SpringBootTest2. Долго…3. @SpringBootTest(classes = ...class)4. Стало быстрее5. С кэшированием конфигураций – еще быстрее

Page 30: Curse of spring boot test

Углубляемся в Spring. Тест #2@ContextHierarchy({ @ContextConfiguration(classes=WordsCommonConfiguration.class), @ContextConfiguration(classes= ...class)})

Page 31: Curse of spring boot test

Demo

Page 32: Curse of spring boot test

Углубляемся в Spring. Тест #2@ContextHierarchy({ @ContextConfiguration(classes=WordsCommonConfiguration.class), @ContextConfiguration(classes=....class)})

Порядок важен! Т.к другая конфигурация использует бины из WordsCommonConfiguration

Page 33: Curse of spring boot test

Но ничего не закешировалось. Тест #2

Page 34: Curse of spring boot test

Но ничего не закешировалось. Тест #2

@SpringBootTest – должен быть везде

Page 35: Curse of spring boot test

Но ничего не закешировалось. Тест #2

@SpringBootTest – должен быть везде@Import – должен быть нигде

Page 36: Curse of spring boot test

Но ничего не закешировалось. Тест #2

@SpringBootTest – должен быть везде@Import – должен быть нигде@ActiveProfiles – один на всех

Page 37: Curse of spring boot test

Но ничего не закешировалось. Тест #2

@SpringBootTest – должен быть везде@Import – должен быть нигде@ActiveProfiles – один на всехSpringBootTest.properties – должны быть одинаковые

Page 38: Curse of spring boot test

Но ничего не закешировалось. Тест #2

@SpringBootTest – должен быть везде@Import – должен быть нигде@ActiveProfiles – один на всехSpringBootTest.properties – должны быть одинаковые

Порядок важен!Любая перестановка – cache miss

Page 39: Curse of spring boot test

Но ничего не закешировалось. Тест #2

@SpringBootTest(properties={"a=b","b=a"})@SpringBootTest(properties={"b=a","a=b"})

Page 40: Curse of spring boot test

Но ничего не закешировалось. Тест #2

@SpringBootTest(properties={"a=b","b=a"})@SpringBootTest(properties={"b=a","a=b"})

Кэш не сработает

Page 41: Curse of spring boot test

Но ничего не закешировалось. Тест #2

@SpringBootTest – должен быть везде@Import – должен быть нигде@ActiveProfiles – один на всехSpringBootTest.properties – должны быть одинаковые

Page 42: Curse of spring boot test

Хрупкий кэш

Все может привести к потере кэша

Page 43: Curse of spring boot test

Пользуемся силойlogging.level.org.springframework.test.context.cache=debug

Page 44: Curse of spring boot test

Б – безопасность@SpringBootTest@ActiveProfiles("yegor_vs_jbaruch")public abstract class ResolversAbstractCommonConfiguration {

}

Page 45: Curse of spring boot test

А если наоборот?

Page 46: Curse of spring boot test

А если наоборот?@DirtiesContext(...)

Page 47: Curse of spring boot test

А если наоборот?@DirtiesContext(...)

methodMode() default MethodMode.AFTER_METHODclassMode() default ClassMode.AFTER_CLASS...

Page 48: Curse of spring boot test

Проверим наши знания. Тест #31. протестируем AnswerCacheServiceJPABackend

Page 49: Curse of spring boot test

Spring Boot обновки

1. @SpringBootTest2. @MockBean && @SpyBean3. @TestConfiguration4. @DataJpaTest5. @MockMvcTest

Page 50: Curse of spring boot test

Синергия с Mockito1. @MockBean/@SpyBean2. @PostConstruct для настройки3. @Bean для настройки конкретных моков

Page 51: Curse of spring boot test

1. Запустим все тесты

Все ли хорошо?

Page 52: Curse of spring boot test

1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает

Все ли хорошо?

Page 53: Curse of spring boot test

1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает3. Загрузил бины из другого теста!

Все ли хорошо?

Page 54: Curse of spring boot test
Page 55: Curse of spring boot test

Spring Boot обновки

1. @SpringBootTest2. @MockBean && @SpyBean3. @TestConfiguration4. @DataJpaTest5. @MockMvcTest

Page 56: Curse of spring boot test

1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает3. Загрузил бины из другого теста!4. @TestConfiguration!

Все ли хорошо?

Page 57: Curse of spring boot test

1. Не сканируется @SpringBootTest2. Не сканируется другими конфигурациями и тестами3. Не прерывает процесс сканирования @SpringBootTest

@TestConfiguration

Page 58: Curse of spring boot test

1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает3. Загрузил бины из другого теста!4. @TestConfiguration!5. DeveloperAssistantApplicationTests.contextLoad работает

Все ли хорошо?

Page 59: Curse of spring boot test

1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает3. Загрузил бины из другого теста!4. @TestConfiguration!5. DeveloperAssistantApplicationTests.contextLoad работает6. А AnswerCacheServiceJPABackendTest перестал7. Загрузил бины из другого теста!

Все ли хорошо?

Page 60: Curse of spring boot test
Page 61: Curse of spring boot test

1.

Как @SpringBootTest сканирует пакеты

Page 62: Curse of spring boot test

Два процесса сканирования1. @SpringBootTest сканирование2. @SpringBootApplication (@ComponentScan)

Page 63: Curse of spring boot test

Два процесса сканирования1. @SpringBootTest сканирование2. @SpringBootApplication (@ComponentScan)

Вверх

Page 64: Curse of spring boot test

Два процесса сканирования1. @SpringBootTest сканирование2. @SpringBootApplication (@ComponentScan) Вниз

Вверх

Page 65: Curse of spring boot test

@SpringBootTest

Два процесса сканирования

Page 66: Curse of spring boot test

@SpringBootTest

Два процесса сканирования

Page 67: Curse of spring boot test

@SpringBootTest

Два процесса сканирования

Page 68: Curse of spring boot test

Два процесса сканирования

@SpringBootTest

Page 69: Curse of spring boot test

Два процесса сканирования

@SpringBootTest

test classpath extends main classpath

Page 70: Curse of spring boot test
Page 71: Curse of spring boot test

Два процесса сканирования

@SpringBootTest

@SpringBootApplication

src/main будет так же просканирован*

test classpath extends main classpath

Page 72: Curse of spring boot test

Два процесса сканирования

@SpringBootTest

@SpringBootApplication

src/main будет так же просканирован*

test classpath extends main classpath

Page 73: Curse of spring boot test

Два процесса сканирования

@SpringBootTest

@SpringBootApplication

src/main будет так же просканирован*

test classpath extends main classpath

Page 74: Curse of spring boot test

Два процесса сканирования

@SpringBootTest

@SpringBootApplication

src/main будет так же просканирован*

test classpath extends main classpath

Page 75: Curse of spring boot test

Два процесса сканирования

@SpringBootTest

@SpringBootApplication

src/main будет так же просканирован*

test classpath extends main classpath

Page 76: Curse of spring boot test

Тоже и сsrc/main/**

Page 77: Curse of spring boot test

1. Запустим все тесты2. DeveloperAssistantApplicationTests.contextLoad падает3. Загрузил бины из другого теста!4. @TestConfiguration!5. DeveloperAssistantApplicationTests.contextLoad работает6. А AnswerCacheServiceJPABackendTest перестал7. Загрузил бины из другого теста!8. @SpringBootConfiguration остановит сканирование

Все ли хорошо?

Page 78: Curse of spring boot test

@SpringBootConfigurationpublic class StopConfiguration {

}

Чиним

Page 79: Curse of spring boot test

Component Tests

Page 80: Curse of spring boot test

Spring Boot обновки

1. @SpringBootTest2. @TestConfiguration3. @MockBean && @SpyBean4. @DataJpaTest5. @MockMvcTest

Page 81: Curse of spring boot test

@DataJpaTest

1. сканирует все репозитории

Page 82: Curse of spring boot test

@DataJpaTest

1. сканирует все репозитории2. конфигурирует EntityManager3. загружает другие конфигурации

Page 83: Curse of spring boot test

1. сканирует все репозитории2. конфигурирует EntityManager3. загружает другие конфигурации4. фильтрует все не относящееся к Data/JPA

Применим знания

@DataJpaTest

Page 84: Curse of spring boot test

Тестируем DefaultAssistantJpaBackendTest1. @DataJpaTest не загружает компоненты Spring

Page 85: Curse of spring boot test

Тестируем DefaultAssistantJpaBackendTest1. @DataJpaTest не загружает компоненты Spring2. Делаем конфигурацию, загружаем недостающее

Page 86: Curse of spring boot test

Тестируем DefaultAssistantJpaBackendTest1. @DataJpaTest не загружает компоненты Spring2. Делаем конфигурацию, загружаем недостающее3. Ничего не работает, из за @SpringBootConfiguration

Page 87: Curse of spring boot test

Тестируем DefaultAssistantJpaBackendTest1. @DataJpaTest не загружает компоненты Spring2. Делаем конфигурацию, загружаем недостающее3. Ничего не работает, из за @SpringBootConfiguration4. Переносим в новый package – все @*Test тесты должны быть

изолированы

Page 88: Curse of spring boot test

@WebMvcTest

1. Не грузит компоненты спринга

Page 89: Curse of spring boot test

@WebMvcTest

1. Не грузит компоненты спринга2. Грузит только то что относится к Web

Page 90: Curse of spring boot test

@WebMvcTest

1. Не грузит компоненты спринга2. Грузит только то что относится к Web3. Сразу изолируем в отдельный пакет

Получаем суперспособность:

@AutowiredMockMvc mockMvc;

Page 91: Curse of spring boot test

Где настраивать @MockBean1. В @*Configuration –

если мок нужен на этапе создания контекста2. В тесте (@Before/setup/etc)

если мок нужен только на этапе выполнения теста

Page 92: Curse of spring boot test

Что же делает @SpringBootTest1. Без classes

a. сканирует со своего пакета “вверх” в поисках @SpringBootConfigurationi. игнорирует остальных

b. падает если не находит или находит несколько в одном пакете

2. classes=~@Configurationa. поднимет только указанные конфигурации

3. classes=~@TestConfigurationa. поднимет указанный контекст и продолжит сканирование. см пункт 1

Page 93: Curse of spring boot test

Зачем нужен @SpringBootTest1. Полный тест на весь контекст2. Изменение properties3. Тесты с определенным скоупом – пакет/конфигурация/автоскан

Page 94: Curse of spring boot test

Зачем нужен @TestConfiguration1. Если нужно не прерывать сканирование @SpringBootTest2. Изолированные тесты (игнорируется при сканировании)

Page 95: Curse of spring boot test

Зачем нужен @SpringBootConfiguration1. Прерывать сканирование инициированное @SpringBootTest

Page 96: Curse of spring boot test

Выводы1. Spring для Unit тестирования может быть быстрым

Page 97: Curse of spring boot test

Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука

Page 98: Curse of spring boot test

Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука3. Для тестов – только @TestConfiguration

Page 99: Curse of spring boot test

Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука3. Для тестов – только @TestConfiguration4. Изолировать группы тестов с помощью

Page 100: Curse of spring boot test

Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука3. Для тестов – только @TestConfiguration4. Изолировать группы тестов с помощью

a. выделения в пакетыb. @SpringBootConfiguration

Page 101: Curse of spring boot test

Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука3. Для тестов – только @TestConfiguration4. Изолировать группы тестов с помощью

a. выделения в пакеты (особенно для @*Test)b. @SpringBootConfiguration

5. SpringBootTest надо в основном использоватьдля микросервис тестов

Page 102: Curse of spring boot test

Выводы1. Spring для Unit тестирования может быть быстрым2. Кэш контекстов – хрупкая штука3. Для тестов – только @TestConfiguration4. Изолировать группы тестов с помощью

a. выделения в пакетыb. @SpringBootConfiguration

5. SpringBootTest надо в основном использоватьдля микросервис тестов

6. Если есть DirtiesContext – стоит задуматься :)

Page 103: Curse of spring boot test

Шкала Тестов

UnitComponent Test

Microservice TestSystem Test

➯ ➯➯ ➯ Следующий доклад

Page 104: Curse of spring boot test

Unit Component Microservice

Что нужно Junit/Mockito @ContextConfiguration @SpringBootTest

Кто управляет new Spring Spring Boot

Page 105: Curse of spring boot test

QA

105

Page 106: Curse of spring boot test

1. @ComponentScan > @TestConfiguration > @Configuratin! @ComponentScan находит даже @TestConfiguration

2. @DataJpaTest > @SpringBootTest3. @DataJpaTest и @WebMvcTest должны быть в отдельных пакетах

Если есть сомнения – смотри автора! Juergen Hoeller*

Дополнительно