Acerca de:

Este blog contiene los códigos, ejemplos y bases de datos que he usado cuando aprendía acerca de algún tema específico. En lugar de borrarlos (una vez dominado ya el tema), he decidido publicarlos :)

lunes, 29 de abril de 2024

El objeto RestTemplate devuelve nulo al testearlo con Mockito

Tuve el mismo problema que ponen en esta pregunta.

En la pregunta se tiene este método en una clase:

public CustomerResponse someMethod() {
    CustomerResponse response = restTemplate.exchange(url, 
    HttpMethod.GET, null, CustomerRes.class).getBody();
    return response;
}

Y se testea con este código:

public void checkResponseIsNotNull() {
    CustomerResponse customerResponseMock = 
    mock(CustomerResponse.class);
    when(restTemplate.exchange(url, HttpMethod.GET, null
    CustomerResponse.class).getBody()).
    thenReturn(customerResponseMock);
    CustomerResponse cr = service.someMethod();
    Assert.assertNotNull(cr);
}

Lo malo es que el objeto restTemplate devuelve nulo al llamar a su método exchange(), luego comprobé que también devuelve nulo en el caso de que se llame a su método postForEntity(). En otros casos el objeto restTemplate devuelve un response nulo.

La solución está aquí. Como escribí en mi comentario, para "mockear" un objeto restTemplate se deben cumplir dos condiciones: 

1. Los parámetros que se le pasan al mock del objeto restTemplate deben ser del mismo tipo que los que se le pasan a sus funciones exchange() o postForEntity().

2. Se debe mockear también el objeto response.

Un código de ejemplo está a continuación:

Class MyClass{
    RestTemplate restTemplate;
    ... some other code...
    
    MyClass(RestTemplate restTemplate){
        this.restTemplate = restTemplate;
    }
    
    public
MyResponseClass funcion(Uri uripath, SomeClass clase) {

    ... add some headers ...

HttpEntity<SomeClass> requestEntity = new HttpEntity<>(clase, headers);

    ResponseEntity<MyResponseClass> responseEntity = this.restTemplate.postForEntity(uripath, requestEntity, MyResponseClass.class);
        return responseEntity.getBody();
    }
}


Test:

@Mock
private RestTemplate restTemplate;

@Test
void Testit{

    SomeClass clase = new SomeClass();
    
    MyResponseClass response = new MyResponseClass();
    response.setValue("OMG");
    ResponseEntity reMock = mock(ResponseEntity.class);
    
    when(reMock.getBody()).thenReturn(response);
    when(this.restTemplate.postForEntity(any(URI.class), any(RequestEntity.class), eq(MyResponseClass.class))).thenReturn(reMock);

    MyClass otherClass = new MyClass(restTemplate);
    MyResponseClass finalResponse = otherClass.funcion(someuri, clase);
    assertThat(finalResponse, is(notNullValue()));
    assertThat(
finalResponse.getValue(), is("OMG"));
}