Тестирование вместе с Spring Boot. Часть 2
В прошлой части мы рассмотрели тестирование слоя контроллера, в этой части давайте рассмотрим поближе тестирование бизнес-слоя и слоя JPA-репозиториев.
К примеру у нас есть следующий код:
// ru.otus.example.Main @EnableJpaRepositories @SpringBootApplication public class Main { public static void main(String[] args) { SpringApplication.run(Main.class); } } // ru.otus.example.jpa.PersonRepository public interface PersonRepository extends JpaRepository<Person, Integer> { } // ru.otus.example.service.PersonServiceImpl public class PersonServiceImpl implements PersonService { private final PersonRepository repository; @Autowired public PersonServiceImpl(PersonRepository repository) { this.repository = repository; } @Override public Person getById(int id) { repository.getOne(id); } // И ещё, конечно, какие-то методы, и их много }
В данном примере у нас имеется SpringBoot-приложение с JPA-репозиторием и бизнес-сервисом, который работает, в частности, с репозиторием.
Чтобы протестировать сервис (бизнес-слой) в принципе не нужен SpringBoot — всегда можно создать моки (в данном случае PersonRepository), и если класс написан в соответствии с IoC, то нам вполне этого достаточно.
А можем всё-таки использовать аннотацию
Итак, тест выглядит следующим образом:
@RunWith(SpringRunner.class) @SpringBootTest public class PersonServiceTests { @MockBean private PersonRepository personRepository; @Autowired private PersonService personService @Test public void testGetById() { given(this.personRepository.getById(any())) .willReturn(new Person(42, "Ivan")); Person person = personService.getById(42); assertThat(person.getId()).isEqualTo(42); // и какие-нибудь другие проверки } }
Разберёмся немного, как работает аннотация SpringBootTest:
1. Тест c
Подобная аннотация SpringBootTest позволяет также писать интеграционные тесты. В данном примере будет использоваться уже реальный JPA-репозиторий.
@RunWith(SpringRunner.class) @SpringBootTest public class PersonServiceTests { @Autowired private PersonService personService @Test public void testGetByIdFromDb() { Person person = personService.getById(42); // уже из базы assertThat(person.getId()).isEqualTo(42); // и какие-нибудь другие проверки } }
Такие тесты используют настроенную в application.yml базу данных. В принципе, JPA-репозитории можно тестировать на embedded DB без особых проблем. Конечно, использование нативных SQL-скриптов и хранимых процедур сказывается на возможности и смысле такого тестирования. Но если вы используете только чистый JPA и, например, liquibase в формате YAML, то корректность маппингов проверить можно, и даже нужно — это позволит избежать ошибок на реальной БД.
И выглядит тест на JPA вот таким образом:
@RunWith(SpringRunner.class) @DataJpaTest @Transactional(propagation = Propagation.NOT_SUPPORTED) public class PersonRepositoryTest { @Autowired private PersonRepository personRepository; // вот такой тест позволит выявить ошибки в маппинге // тестировать другие методы в репозитории по большей части не нужно @Test public void testSaveAndGet() { personRepository.getById(new Person(42, "Ivan")); Person fromDb = personRepository.getOne(42); assertThat(fromDb.getId).isEqualTo(42); // и какие-нибудь другие проверки на поля } }
На этом всё. Оставим читателю возможность самому изучить, всё-таки, на какой БД это будет выполнено!
Есть вопрос? Пишите комментарий!