Versiones comparadas

Clave

  • Se ha añadido esta línea.
  • Se ha eliminado esta línea.
  • El formato se ha cambiado.

...

Bloque de código
import static org.junit.jupiter.api.Assertions.assertThrows;

assertThrows( TokenExpiredException.class, () -> jwtTokenUtil.getClaim( "Bearer " + tokenCaducado ) );
assertThrows( UnauthorizedException.class, () -> jwtTokenUtil.getClaim( "asdf" ) );

...

Mock

Un mock es una simulación de un objeto real; nos permite simular su comportamiento de forma aislada, eliminando dependencias. A efectos prácticos, un objeto mock será un objeto de la clase que indiquemos, cuyos métodos devolverán null por defecto. Para crear estos mocks y definir el comportamiento de los métodos que nos interesen, utilizamos Mockito. Vamos a ver cada uno de estos pasos, primero cómo crear un mock, y después cómo personalizar el comportamiento de los métodos.

Crear mocks

Mockito.mock() - Mock de un objeto

Con el método Mockito.mock() podemos crear un mock de un objeto de una clase o interfaz. Esto es, el mock se aplicará únicamente a ese objeto. Si es un bean que por ejemplo utilice otra clase, este mock no se aplicará a ese bean, únicamente al objeto que hemos indicado. Lo haremos así, dentro de un test:

Bloque de código
languagejava
UserRepository localMockRepository = Mockito.mock(UserRepository.class);

@Mock - Mock de un objeto (propiedad de la clase de test)

Podemos indicar en las propiedades de nuestra clase que contiene los tests, que estas sean mocks. Esto es, al igual que en el caso anterior, que sólo se apliquen a estos objetos. Lo haremos con la anotación @Mock:

Bloque de código
languagejava
@Mock
UserRepository mockRepository;

@MockBean - Mock de un bean a nivel global

Por último, podemos añadir la anotación @MockBean  las propiedades de la clase, que creará el mock a nivel global, de contexto. Esto quiere decir que todas las instancias de ese bean serán ese mock, en lugar de únicamente el objeto que definimos en la clase de los tests. Esto se aplicará a todos los tests que tengamos en la clase.

Bloque de código
languagejava
@MockBean
UserRepository mockRepository;

Mockear una propiedad de un objeto

Podemos mockear una propiedad de un objeto como hemos visto en un ejemplo anterior, utilizando ReflectionTestUtils.setField, indicando el objeto, el nombre de la propiedad, y el valor a asignarle:

Bloque de código
languagejava
@Autowired
JwtTokenUtil jwtTokenUtil;

@BeforeEach
void mocksecret() {
	ReflectionTestUtils.setField( jwtTokenUtil, "secret", "secreto" );
}

Mockear un método

Para hacer un mock de un métidométodo, disponemos de Mockito.when(...), al que le indicamos el método, con sus argumentos, y que posteriormente nos ofrece varios métodos para la respuesta, como .thenReturn( ... ) para indicar el valor a devolver o .thenThrow( ... ) para indicar una excepción a lanzar. En el siguiente ejemplo podemos ver dos ejemplos de esto para hacer un mock de getClaims, creando un token previamente, pasando un valor concreto como argumento o indicando que cualquier String:

Bloque de código
languagejava
import static org.mockito.ArgumentMatchers.any;

...

Map<String, Object> infoUser = new HashMap<>();
infoUser.put( "roleName", "G_OTROS" );
final Instant now = Instant.now();
// Creamos token con el usuario "guillermo.castillo@ticarum.es", codificado con el secret "secreto"
String token = Jwts.builder().setClaims( infoUser ).setSubject( "guillermo.castillo@ticarum.es" )
		.setIssuedAt( Date.from( now ) ).setExpiration( Date.from( now.plus( Duration.ofDays( 123 ) ) ) )
		.signWith( SignatureAlgorithm.HS256, TextCodec.BASE64.encode( "secreto" ) ).compact();

final Claims claims = Jwts.parser().setSigningKey( TextCodec.BASE64.encode( "secreto" ) ).parseClaimsJws( token ).getBody();

// Mock getClaims
Mockito.when( jwtTokenUtil.getClaim( "asdf" ) ).thenReturn(claims);

// Mock getClaims con cualquier argumento String
Mockito.when( jwtTokenUtil.getClaim( any(String.class) ).thenReturn(claims);

Aquí vemos que en el último when, el argumento que se le pasa a getClaim es any(String.class), indicando que cuando se ejecute ese método con cualquier argumento que sea de tipo String, se devolverá lo que se indica. Al igual que any, podemos utilizar nullable, para indicar que puede ser o de la clase que indiquemos, o null. Para esto tendremos que añadir sus imports, que al ser static no nos los autocompletará Eclipse:

Bloque de código
languagejava
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.nullable;

Spy

A parte de hacer mocks, tenemos la opción de utilizar Spy, que en vez de crear un objeto falso, lo que nos permite es interceptar partes del objeto original. Se puede ver como un mock parcial, para por ejemplo simular el comportamiento de algunos métodos, pero manteniendo el comportamiento por defecto del resto. La forma de hacer esto es muy similar a los mocks, pero para simular el comportamiento de las llamadas a los métodos cambia un poco la sintaxis. Vamos a verlo.

Info

En proceso...

Simular peticiones a servicio REST

...