cualquier comparador() para el campo @Value genera un error de discrepancia en el argumento de creación estricta.
¿Existe algún ArgumentMatcher propio del campo @Value? ¿Y tal vez alguien sepa por qué 'any()' no funciona?
El campo (sampleVersion), que obtengo de application.properties usando la anotación @Value, tiene en la prueba un valor nulo (prueba: primera línea de registros). Incluso los registros muestran que hay un valor nulo y que el comparador espera un valor nulo.
PD: resolví este problema usando esto:
ReflectionTestUtils.setField(someClass, "serviceUrl", "value");
pero tengo curiosidad por saber si es necesario y por qué el simple any() no funciona.
Registros:
sampleVersion has value: null
Strict stubbing argument mismatch. Please check:
- this invocation of 'postForEntity' method:
restTemplate.postForEntity(
null,
<{key=null},[Content-Type:"application/json"]>,
class java.lang.String
);
-> at com.some.package.SomeClass.someMethod(SomeClass.java:126)
- has following stubbing(s) with different arguments:
1. restTemplate.postForEntity(null, null, null);
-> at com.some.package.SomeClassTest.someTest(SomeClassTest.java:59)
Método:
@Value("${sample.version}")
private String sampleVersion;
public ResponseEntity someMethod() {
System.out.println("sampleVersion has value: " + sampleVersion);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("key", sampleVersion);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return restTemplate.postForEntity(sampleVersion, new HttpEntity<>(paramMap, headers), String.class);
}
Prueba:
@InjectMocks
SomeClass someClass = new SomeClass();
@Test
void someTest() {
//given
ResponseEntity response = new ResponseEntity("{ \"text\" : \"hello\"}", HttpStatus.OK);
//when
when(restTemplate.postForEntity(any(), any(), eq(String.class))).thenReturn(response);
ResponseEntity responseEntity = someClass.someMethod();
assertNotNull(responseEntity);
}
Medio ambiente:
Java 11
SpringBoot 2.1.4
Mockito 2.27.0
Júpiter 5.3.2
------------------------------------
Hay 2 sobrecargas de postForEntity que podrían tomar 3 parámetros:
<T> EntidadRespuesta<T> postForEntity(URL de cadena, Solicitud de objeto, Clase<T> tipo de respuesta, Objeto... uriVariables)
<T> EntidadRespuesta<T> postForEntity(URL URI, solicitud de objeto, clase<T> tipo de respuesta)
En tu código de producción, estás llamando al primero.
En tu prueba, eliminas el segundo.
Esto se debe al hecho de que en su llamada:
when(restTemplate.postForEntity(any(), any(), eq(String.class))).thenReturn(response);
Usted proporciona 3 argumentos y los valores proporcionados coinciden con los tipos de parámetros de la segunda sobrecarga.
Por lo tanto, ni siquiera se considera la sobrecarga con varargs.
(any() devuelve nulo, lo cual es una buena coincidencia tanto para URI como para cadena).
En lugar dereflexión, le aconsejaría:
utilizar la inyección de constructor para sampleVersion
suelte @InjectMocks en el servicio bajo prueba
en su lugar, cree el servicio bajo prueba en un método BeforeEach.
------------------------------------
Escribo esto en las respuestas porque el autor puso la solución en la pregunta. (Esto es para una mejor visibilidad). El autor pudo resolver el problema usando
ReflectionTestUtils.setField(someClass, "field", "value");
Esto puede asignar un valor al campo privado con fines de prueba. El valor no lo asigna la anotación @Value durante la prueba automatizada.
Para obtener más información sobre el uso: https://www.baeldung.com/spring-reflexión-test-utils#uso-reflexióntestutils-para-establecer-un-valor-de-un-campo-no-público