Reputation: 91
any()
matcher for @Value field gives Strict stubbing argument mismatch
error.
Is there any ArgumentMatcher
proper to @Value field? And maybe someone knows why 'any()' is not working?
Field (sampleVersion
), which I get from application.properties using @Value annotation, has in test value null
(proof - first line of logs). Even logs show that there is null
and matcher expected null
.
PS I solved this problem using this:
ReflectionTestUtils.setField(someClass, "serviceUrl", "value");
but I'm curious is it necessary and why simple any()
doesn't work.
Logs:
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)
Method:
@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);
}
Test:
@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);
}
Environment:
Java 11
SpringBoot 2.1.4
Mockito 2.27.0
Jupiter 5.3.2
Upvotes: 2
Views: 2809
Reputation: 51
I'm writing this into the answers because the author put the solution into the question. (This is for better visibility.) The author was able to resolve the issue using
ReflectionTestUtils.setField(someClass, "field", "value");
This can assign the private field a value for testing purposes. The value is not assigned by the @Value
annotation during the automated test.
For more information on usage: https://www.baeldung.com/spring-reflection-test-utils#using-reflectiontestutils-to-set-a-value-of-a-non-public-field
Upvotes: 0
Reputation: 26084
There are 2 overloads of postForEntity
that could take 3 parameters:
<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
<T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType)
In your production code, you are calling the first one.
In your test, you stub the second one instead. This stems from the fact that in your call:
when(restTemplate.postForEntity(any(), any(), eq(String.class))).thenReturn(response);
You provide 3 arguments, and the values provided match types of parameters of the second overload. Thus the overload with varargs is not even considered. (any() returns null, which is a good match for both URI and String).
Instead of reflection, I would advise to:
Upvotes: 1