Како тестирати услуге, крајње тачке и спремишта у Спринг Боот-у

У овом посту ћу вам показати како да напишете јединичне тестове у пролећним апликацијама за покретање.

Зашто је потребно писати јединствени тест, потребно је објаснити други чланак. Али за кратко објашњење, рећи ћу вам неколико ствари.

Обично браним аргумент да је код без јединичних тестова мртав код. Јер, када програмер дода нову функцију неком коду који није обухваћен јединственим тестом, склон је надјачавању постојећих пословних правила (што убија претходно написани код). Можда није баш склоно томе, али можете замислити какве грешке могу настати када сложени пројекат треба променити. Јединствено тестирање је једини начин да заштитите свој код од прекида промена.

Зашто јединичне тестне тачке?

Сваки пут када напишемо крајњу тачку морамо бити сигурни да неколико ствари исправно ради. Крајња тачка треба да врати податке у исправној структури и правилно обрађује захтев. Можемо га тестирати ручно, што није пожељно. Дакле, пишемо јединствене тестове како бисмо осигурали да наше крајње тачке раде исправно. Постоји и други начин за тестирање крајњих тачака познат под називом тестови аутоматизације, али то није тема овог поста.

Зашто услуге јединичног тестирања?

То би већ требало да буде јасно, али за сваки случај: морамо бити сигурни да наша пословна логика исправно ради.

Зашто репозиторијуми јединствених тестова?

Постоји неколико случајева за тестирање спремишта. Наравно да не тестирамо сам оквир. Али ми пишемо јединичне тестове како бисмо били сигурни да су наше спецификације или односи правилно примењени.

Па како тестирати контролере?

Сада је време да вам покажемо како да тестирате наше контролере у пролећном покретању. Замислимо да напишемо апликацију која нам омогућава да сачувамо кориснике у бази података. Дефинишемо кориснички ентитет, корисничку услугу и контролер.

Напомена: Примери приказани у овом посту нису за стварну архитектуру употребе

@[email protected] class User { @Id @GeneratedValue(generator = "uuid2") @GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator") @Column(name = "id", columnDefinition = "BINARY(16)") private UUID id; private String name; private String email; private int age;}
@Datapublic class CreateUserRequest { private String name; private String email; private int age;}
@[email protected]("/users")public class UserController { UserService userService; @Autowired public UserController(UserService userService) { this.userService = userService; } @PostMapping public ResponseEntity createUser(@RequestBody CreateUserRequest request) { User created = userService.save(request); return ResponseEntity.ok(created); }}

Наш контролер има зависност од УсерСервице, али нас не занима шта услуга тренутно ради.

Дакле, хајде да напишемо јединствени тест за наш контролер како бисмо били сигурни да ради исправно.

Исмијали смо нашу услугу јер нам нису потребни детаљи о њеној примени. Овде само тестирамо наш контролер. Овде користимо MockMvcда тестирамо свој контролер и мапирање објеката у сврхе сериализације.

Постављамо нашу userService.Save() методу за враћање жељеног корисничког објекта. Прошли смо захтев за нашу контролер и након тога смо проверавали враћене податке са следећим линије: andExpect(jsonPath("$.name").value(request.getName())).

Имамо и друге методе. Ево листе метода:

Када покренемо тест, видимо да је прошао.

Како тестирамо услуге?

Сада идемо да тестирамо нашу УсерСервице. Тесто је прилично једноставно тестирати.

Изругујемо се спремишту и убацујемо своје подсмехе у УсерСервице. Сада када покренемо тест, видећемо да ли је прошао.

Сада додамо пословно правило у УсерСервице: рецимо да корисник мора имати адресу е-поште.

Мењамо метод чувања у УсерСервицеу на следећи начин:

public User save(CreateUserRequest request) { requireNonNull(request.getEmail()); User user = new User(); user.setName(request.getName()); user.setEmail(request.getEmail()); user.setAge(request.getAge()); userRepository.save(user); return user;}

Када поново покренемо тест, видећемо неуспели тест.

Пре него што то поправимо, напишимо тест који задовољава овај посао.

Написали смо нови тест који је прецизирао да ће га послати ако пошаљемо нулу е-пошту NullPointerException.

Поправимо неуспели тест додавањем е-поште нашем захтеву:

createUserRequest.setEmail("testemail");

Покрените оба теста:

Како тестирамо спремишта?

Сада смо дошли до тестирања спремишта. Користимо базу података у меморији х2 саTestEntityManager.

Наше спремиште је дефинисано на следећи начин:

@Repositorypublic interface UserRepository extends JpaRepository, JpaSpecificationExecutor { Optional findById(UUID id);}

Прво конфигуришите х2дб. Направите име датотеке апплицатион.иамл у тест -> патх патх:

spring: application: name: Spring Boot Rest API datasource: type: com.zaxxer.hikari.HikariDataSource url: "jdbc:h2:mem:test-api;INIT=CREATE SCHEMA IF NOT EXISTS dbo\\;CREATE SCHEMA IF NOT EXISTS definitions;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false;MODE=MSSQLServer" name: password: username: initialization-mode: never hikari: schema: dbo jpa: database: H2 database-platform: org.hibernate.dialect.H2Dialect show-sql: true hibernate: ddl-auto: create-drop test: database: replace: none

И хајде да прво напишемо основни тест за наше спремиште: спасите корисника и преузмите га:

@RunWith(SpringRunner.class)@DataJpaTestpublic class UserRepositoryTest { @Autowired TestEntityManager entityManager; @Autowired UserRepository sut; @Test public void it_should_save_user() { User user = new User(); user.setName("test user"); user = entityManager.persistAndFlush(user); assertThat(sut.findById(user.getId()).get()).isEqualTo(user); }}

Када га покренемо, видећемо гомилу излаза конзоле, а такође и тест који пролази:

Хајде сада да додамо још један метод у наше спремиште за тражење корисника путем е-поште:

Optional findByEmail(String email);

И напишите још један тест:

@Testpublic void it_should_find_user_byEmail() { User user = new User(); user.setEmail("[email protected]"); user = entityManager.persistAndFlush(user); assertThat(sut.findByEmail(user.getEmail()).get()).isEqualTo(user);}

Када погледамо конзолу након покретања теста, видећемо СКЛ генерисан хибернате:

SELECT user0_.id AS id1_1_,user0_.age AS age2_1_,user0_.email AS email3_1_,user0_.name AS name4_1_FROM user user0_WHERE user0_.email=?

Засада је добро. Основе јединичног тестирања покрили смо опружним пртљажником.

Сада немате изговора да не напишете јединствене тестове! Надам се да вам је јасно како да напишете јединствене тестове за различите сврхе.