Cómo probar servicios, puntos finales y repositorios en Spring Boot

En esta publicación, le mostraré cómo escribir pruebas unitarias en aplicaciones de arranque de primavera.

Por qué es necesario escribir una prueba unitaria requiere otro artículo para explicar. Pero para una breve explicación, te diré varias cosas.

Normalmente defiendo el argumento de que el código sin pruebas unitarias es código muerto. Porque, cuando un desarrollador agrega una nueva característica a algún código que no está cubierto por una prueba unitaria, es propenso a anular las reglas comerciales existentes (lo que elimina el código escrito antes). Tal vez no sea exactamente propenso a ello, pero puede imaginarse qué errores pueden ocurrir cuando es necesario cambiar un proyecto complejo. Las pruebas unitarias son la única forma de proteger su código contra cambios importantes.

¿Por qué realizar pruebas unitarias en los puntos finales?

Cada vez que escribimos un punto final, debemos asegurarnos de que varias cosas funcionen correctamente. El punto final debe devolver los datos en la estructura correcta y manejar la solicitud correctamente. Podemos probarlo manualmente, lo cual no es preferible. Entonces escribimos pruebas unitarias para asegurarnos de que nuestros puntos finales funcionen correctamente. También hay otra forma de probar puntos finales conocida como pruebas de automatización, pero ese no es el tema de esta publicación.

¿Por qué servicios de prueba unitaria?

Ya debería estar claro, pero por si acaso: debemos estar seguros de que nuestra lógica empresarial funciona correctamente.

¿Por qué probar los repositorios unitarios?

Hay varios casos para probar repositorios. Por supuesto, no probamos el marco en sí. Pero escribimos pruebas unitarias para asegurarnos de que nuestras especificaciones o relaciones se hayan implementado correctamente.

Entonces, ¿cómo probamos los controladores?

Ahora es el momento de mostrarte cómo probar nuestros controladores en Spring Boot. Imaginemos que escribimos una aplicación que nos permite guardar usuarios en una base de datos. Definimos una entidad de usuario, un servicio de usuario y un controlador.

Nota: Los ejemplos que se muestran en esta publicación no son para arquitectura de uso de producción real

@[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); }}

Nuestro controlador depende de UserService, pero no estamos interesados ​​en lo que hace el servicio en este momento.

Así que ahora escribamos una prueba unitaria para nuestro controlador para asegurarnos de que funciona correctamente.

Nos burlamos de nuestro servicio porque no necesitamos sus detalles de implementación. Solo probamos nuestro controlador aquí. Usamos MockMvcaquí para probar nuestro controlador y mapeador de objetos con fines de serialización.

Configuramos nuestro userService.Save() método para devolver el objeto de usuario deseado. Pasamos una solicitud a nuestro controlador y después de que nos registramos los datos devueltos con la siguiente línea: andExpect(jsonPath("$.name").value(request.getName())).

También tenemos otros métodos para utilizar. Aquí está la lista de métodos:

Cuando ejecutamos la prueba, vemos que pasa.

¿Cómo probamos los servicios?

Ahora vamos a probar nuestro UserService. Es bastante sencillo de probar.

Simulamos el repositorio e inyectamos nuestras simulaciones en UserService. Ahora, cuando ejecutemos la prueba, veremos que pasa.

Ahora agreguemos una regla comercial a UserService: digamos que el usuario debe tener una dirección de correo electrónico.

Cambiamos nuestro método de guardado en UserService de la siguiente manera:

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;}

Cuando volvamos a ejecutar la prueba, veremos una prueba fallida.

Antes de solucionarlo, escribamos una prueba que satisfaga este negocio.

Escribimos una nueva prueba que especificaba que si enviamos un correo electrónico nulo, arrojará NullPointerException.

Arreglemos la prueba fallida agregando un correo electrónico a nuestra solicitud:

createUserRequest.setEmail("testemail");

Ejecute ambas pruebas:

¿Cómo probamos los repositorios?

Ahora hemos llegado a probar repositorios. Usamos una base de datos h2 en memoria conTestEntityManager.

Nuestro repositorio se define a continuación:

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

Primero configure h2db. Cree el nombre de archivo application.yaml en prueba -> ruta de recursos:

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

Y primero escriba una prueba básica para nuestro repositorio: guarde un usuario y recupérelo:

@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); }}

Cuando lo ejecutamos, veremos un montón de resultados de la consola, y también nuestra prueba pasa:

Ahora agreguemos otro método a nuestro repositorio para buscar un usuario por correo electrónico:

Optional findByEmail(String email);

Y escribe otra prueba:

@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);}

Cuando echemos un vistazo a la consola después de ejecutar la prueba, veremos el SQL generado por hibernate:

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=?

Hasta aquí todo bien. Hemos cubierto los conceptos básicos de las pruebas unitarias con Spring Boot.

Now you don’t have any excuses to not write unit tests! I hope it is clear to you to how to write unit tests for different kinds of purposes.