Spring: Test
Правила именование
Четких правил именования нет, но рекомендуется классы заканчивать постфиксом *Test
, а методы, проводящие тестирование именовать согласно тому что они проверяют.
1 | public class MyServiceTest { |
JUnit4 vs JUnit5
@Before
->@BeforeEach
@After
->@AfterEach
@BeforeClass
->@BeforeAll
@AfterClass
->@AfterAll
@Test(expected=Exception.class)
->@Test { assertThrows(..., Exception.class) }
@Ignore
->@Disabled
Симуляция
Для тестирования принято разделять объекты-симуляции на 2 вида: mock и stub.
Оба подхода не реализует работу компонента, а создает копию классов, который создает иллюзию работы компонента, реализуя вход и выход в компонент тестовых данных. Например, в случае с работой с БД, можно создать коллекцию, которая будет хранить данные в памяти.
Негативной стороной stub считается долгая реализация симуляции работы компонента. Малейшее изменение оригинального класса так же может повлечь массивных изменений stub компонентов.
Mock
Аналог stub, но предполагает подключение библиотек, которые уже имеют некоторое количество реализаций соответствующих сервисов (например, иммитацию работы репозиториев БД).
Сущесвует ряд библиотек, реализующих mock подход к тестированию. Наиболее популярными являются EasyMock и Mockito.
Пример для EasyMock:
1 | public class MyServiceEasyMockTest { |
Пример для Mockito:
1 |
|
Метод when
создает псевдо-подстановку согласно условию. Тем самым сервис userService
будет возвращать тот объект, который представлен в thenReturn
.
ContextConfiguration
Для теста можно указать специфический загрузчик конфигураций. Это удобно если для 1-го конкретного теста надо изменить поведение компонента:
1 |
|
Доступ к БД
Наиболее примитивным является доступ через JdbcTemplate
. Придется много кода писать самостоятельно, но плюсом является то что запросы можно оптимизировать, а так же то что не используется никаких прокси, все запросы идут напрямую в БД.
1 |
|
Для разбора результатов выполнения запросов (в частности, SELECT) к БД, придется создать RowMapper
, который будет выполнять построчную обработку результатов выборки в БД (например, конвертацию результатов запросов в POJO).
1 |
|
Тесты и SQL
Аннотации из группы @Sql
помогают оптимизировать тестирование под конкретные случаи:
1 |
|
Аннотации из данной группы можно применять и к классу, тогда они будут применены ко всем @Test
методам.
Аннотация @SqlConfig
добавляет правила исполнения скриптов (данная аннотация не часто используется, ввиду низкой потребности) - устанавливает изоляцию транзакций, кодировку чтения скриптов, разделители при чтении скриптов и т.д.
Аннотация @SqlGroup
объединяет несколько @Sql
аннотаций в группу и позволяет выполнять всю группу целиком, в единой транзакции.
В сложном тестировании необходимо подключать транзакции для работы с тестированием БД. Это осуществляется, как и обычно, посредством @Transactional
либо ручным управлением транзакциями.
Аннотация @BeforeTransaction
и @AfterTransaction
помогают управлять началом и завершением транзакции, соответственно.
Для теста, по ум., транзакция всегда откатывается (выполняется rollback
) - тем самым перед каждым тестом данные в БД лежат в эталонном виде. Если это поведение необходимо изменить (т.е. изменения транзакции подтверждались) - необходимо добавить аннотацию @Rollback(false)
. Аналогично работает и @Commit(true)
, который подтверждает транзакцию по окончании тестового метода (по ум. аннотация = @Commit(false)
).
Профили тестирования
Для бина или конфигурации (или любого другого компонента) можно определить Spring профиль при котором он будет создан (и доступен).
1 |
|
Без указания @Profile
, бины создаются всегда и без ограничений.
Для тестов можно указать активный профиль на каждый отдельный класс (т.е. для каждого класса тестирования профили могут различаться):
1 |
|
Параметр inheritProfiles
помечает можно ли наследовать профили от родительских тест-классов (по ум. все профили наследуются, т.е. inheritProfiles=true
).
SpringBoot и тесты
Добавление @SpringBootTest
дает возможность запускать тестирование SpringBoot приложений. При этом, JUnit уже будет подключен как фреймворк для тестирования.
1 |
|
Тестирование с JUnit5
Для 5 версии JUnit необходимо у тестов изменить @RunWith
на @ExtendWith
, присвоив соответствующий параметр в виде нового класса:
1 |
|
Можно сократить аннотацию совместив ее вместе с перечнем конфигураций до:
1 |
Тестирование с JUnit4
Для тестирования Spring создает Singleton бин из класса ApplicationContext
, который является активным на всем протяжении всего жизненного цикла тестов.
Для запуска тестов в контексте Spring необходимо:
- Добавить аннотацию
@RunWith(SpringJUnit4ClassRunner.class)
или@RunWith(SpringRunner.class)
; - Добавить
@ContextConfiguration
с указанием дополнительных конфигураций для контекста (опционально):@ContextConfiguration(locations={"classpath:myConf.yml", "..."})
. Если параметр не указан, то будет использована локация по ум.: {testClassName}-context.xml;
3.Используя@Autowired
или@Inject
, добавить требуемые бины.