Como testar serviços, endpoints e repositórios no Spring Boot

Rurouni Blocked Unblock Seguir Seguindo 1 de janeiro

Neste post vou mostrar-lhe como escrever testes de unidade em aplicativos de inicialização de primavera.

Por que é necessário escrever teste de unidade requer outro artigo para explicar. Mas, para uma breve explicação, vou contar várias coisas.

Eu costumo defender o argumento de que o código sem testes de unidade é código morto. Porque, quando um desenvolvedor adiciona um novo recurso a algum código que não é coberto por um teste de unidade, ele é propenso a sobrescrever as regras de negócios existentes (que mata o código escrito anteriormente). Talvez não seja exatamente propenso a isso, mas você pode imaginar quais erros podem ocorrer quando um projeto complexo precisa ser alterado. O teste unitário é a única maneira de proteger o seu código contra violações.

Por que endpoints de teste de unidade?

Toda vez que escrevemos um endpoint, precisamos ter certeza de que várias coisas funcionam corretamente. O nó de extremidade deve retornar os dados na estrutura correta e manipular a solicitação corretamente. Podemos testá-lo manualmente, o que não é preferível. Então, nós escrevemos testes de unidade para garantir que nossos endpoints funcionem corretamente. Há também outra maneira de testar endpoints conhecidos como testes de automação, mas esse não é o assunto deste post.

Por que serviços de teste unitário?

Já deve estar claro, mas apenas no caso: precisamos ter certeza de que nossa lógica de negócios funciona corretamente.

Por que repositórios de teste de unidade?

Existem vários casos para testar repositórios. Claro que não testamos o framework em si. Mas nós escrevemos testes unitários para ter certeza de que nossas especificações ou relações foram implementadas corretamente.

Então, como testamos os controladores?

Agora é hora de mostrar como testar nossos controladores na inicialização da mola. Vamos imaginar que nós escrevemos um aplicativo que nos permite salvar usuários em um banco de dados. Nós definimos uma entidade de usuário, um serviço de usuário e um controlador.

Nota: Os exemplos mostrados neste post não são para arquitetura de uso de produção real

 @Dados 
@Entidade
public class User {
@Identidade
@GeneratedValue (generator = "uuid2")
@GenericGenerator (name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
@Column (name = "id", columnDefinition = "BINARY (16)")
ID do UUID privado;
private String name;
e-mail private String;
privado int idade;
}
 @Dados 
classe pública CreateUserRequest {
private String name;
e-mail private String;
privado int idade;
}
 @RestController 
@RequestMapping ("/ users")
public class UserController {

UserService userService;

@Autowired
public UserController (UserService userService) {
this.userService = userService;
}

@PostMapping
public ResponseEntity <User> createUser (@RequestBody Pedido de CreateUserRequest) {

Usuário criado = userService.save (request);

return ResponseEntity. ok (criado);
}
}

Nosso controlador depende do UserService, mas não estamos interessados no que o serviço faz agora.

Então, agora vamos escrever um teste de unidade para o nosso controlador para ter certeza de que funciona corretamente.

Nós ridicularizamos nosso serviço porque não precisamos dos detalhes da implementação. Nós apenas testamos nosso controlador aqui. Usamos o MockMvc aqui para testar nosso controlador e mapeador de objetos para fins de serialização.

Nós configuramos nosso método userService.Save() para retornar o objeto de usuário desejado. Nós passamos uma requisição para nosso controller e depois checamos os dados retornados com a seguinte linha: andExpect(jsonPath("$.name").value(request.getName())) .

Temos também outros métodos para usar . Aqui está a lista de métodos:

Quando executamos o teste, vemos que ele passa.

Como podemos testar serviços?

Agora vamos testar nosso UserService. É bastante simples de testar.

Nós zombamos do repositório e injetamos nossos mocks no UserService. Agora, quando fizermos o teste, veremos que ele passa.

Agora vamos adicionar uma regra de negócios ao UserService: digamos que o usuário tenha um endereço de email.

Nós mudamos nosso método save no UserService como abaixo:

 Usuário público salvar (solicitação CreateUserRequest) { 
requireNonNull (request.getEmail ());

Usuário usuário = novo usuário ();
user.setName (request.getName ());
user.setEmail (request.getEmail ());
user.setAge (request.getAge ());

userRepository.save (usuário);

retornar usuário;
}

Quando executarmos o teste novamente, veremos um teste com falha.

Antes de consertar, vamos escrever um teste que satisfaça esse negócio.

Escrevemos um novo teste que especifica que, se enviarmos um email nulo, ele lançará NullPointerException.

Vamos corrigir o teste com falha adicionando um email ao nosso pedido:

 createUserRequest.setEmail ("testemail"); 

Execute os dois testes:

Como testamos repositórios?

Agora chegamos a testar repositórios. Usamos um banco de dados na memória h2 com o TestEntityManager.

Nosso repositório é definido como abaixo:

 @Repositório 
interface pública UserRepository estende JpaRepository <User, Integer>, JpaSpecificationExecutor <User> {
<User> findById (ID do UUID) opcional;
}

Primeiro configure o h2db. Crie o nome do arquivo application.yaml em test -> resources path:

 Primavera: 
aplicação:
nome:
Spring Boot Rest API
fonte de dados:
tipo:
com.zaxxer.hikari.HikariDataSource
url: "jdbc: h2: mem: teste-api; INIT = CREATE SCHEMA SE NÃO EXISTE definições dbo \; CREATE SCHEMA IF NOT EXISTS; DATABASE_TO_UPPER = false; DB_CLOSE_DELAY = -1; DB_CLOSE_ON_EXIT = false; MODO = MSSQLServer"
nome:
senha:
username:
modo de inicialização:
nunca
hikari:
esquema:
dbo
jpa:
banco de dados:
H2
plataforma de banco de dados: org.hibernate.dialect.H2Dialect
show-sql: true
hibernar:
ddl-auto:
criar e soltar
teste:
base de dados:
substituir:
nenhum

E vamos primeiro escrever um teste básico para o nosso repositório: salve um usuário e recupere-o:

 @RunWith (SpringRunner.class) 
@DataJpaTest
public class UserRepositoryTest {
@Autowired
TestEntityManager entityManager;

@Autowired
UserRepository sut;

@Teste
public void it_should_save_user () {
Usuário usuário = novo usuário ();
user.setName ("usuário de teste");

user = entityManager.persistAndFlush (usuário);

assertThat (sut.findById (user.getId ()). get ()). isEqualTo (usuário);
}
}

Quando executamos, veremos a saída do console e também nossos testes:

Agora vamos adicionar outro método ao nosso repositório para procurar um usuário por email:

 <User> findByEmail opcional (e-mail String); 

E escreva outro teste:

 @Teste 
public void it_should_find_user_byEmail () {
Usuário usuário = novo usuário ();
user.setEmail ("testmail@test.com");

user = entityManager.persistAndFlush (usuário);

assertThat (sut.findByEmail (user.getEmail ()). get ()). isEqualTo (usuário);
}

Quando damos uma olhada no console depois de executar o teste, veremos o SQL gerado pelo hibernate:

 SELECT user0_.id AS id1_1_, 
user0_.age AS age2_1_,
user0_.email AS email3_1_,
user0_.name AS name4_1_
FROM usuário user_
WHERE user0_.email =?

Por enquanto, tudo bem. Nós cobrimos as noções básicas de testes unitários com inicialização de mola.

Agora você não tem desculpas para não escrever testes unitários! Espero que esteja claro para você como escrever testes de unidade para diferentes tipos de propósitos.