I have problem testing a service with Spock and Groovy. For this, I try to Stub a method of my client, that calls RestTemplate
with ParameterizedTypeReference
.
NOTE: Sorry for my bulky code!!!
Here my Configuration Class
MyMicroserviceClientConfiguration class
@Data
@Configuration
@ConfigurationProperties(prefix = "clients.my-microservice-client")
public class MyMicroserviceClientConfiguration {
@NotBlank
private String urlDocsByName;
@NotBlank
private String urlSend;
}
Here a Static Classes
Attachment class
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Attachment {
private String idContent;
private String name;
private byte[] bytes;
}
AttachmentList class
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class AttachmentList {
private List<Attachment> attachments;
}
Here my Client Class
MyMicroserviceClientImpl
class
public class MyMicroserviceClientImpl implements MyMicroserviceClient {
private final MyMicroserviceClientConfiguration myMicroserviceClientConfiguration;
private final RestTemplate restTemplate;
@Override
public AttachmentList getDocsByName(String idContent, String name) {
Map<String, String> uriVars = new HashMap<>();
uriVars.put("idContent", idContent);
UriComponents builder = UriComponentsBuilder.fromHttpUrl(myMicroserviceClientConfiguration.getUrlDocsByName())
.queryParam("pattern", name)
.buildAndExpand(uriVars);
ResponseEntity<List<Attachment>> response = restTemplate.exchange(builder.toUriString(),
HttpMethod.GET,
new HttpEntity<>(null),
new ParameterizedTypeReference<List<Attachment>>() { }); // I need Stub this Call
return AttachmentList.builder().attachments(response.getBody()).build();
}
@Override
public void processList(List<AttachmentDTO> request) {
try {
restTemplate.postForEntity(myMicroserviceClientConfiguration.getUrlSend(),
request,
byte[].class);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Other Classes
CustomResponse class
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CustomResponse {
private String nameDocument;
private String code;
private int qtySent;
}
AttachmentDTO class
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class AttachmentDTO {
@JsonProperty("typeDocument")
private String typeDocument;
@JsonProperty("name")
private String name;
@JsonProperty("base64Content")
private String base64Content;
}
My Service Class
MyServiceImpl
class
@Service
@RequiredArgsConstructor
public class MyServiceImpl implements MyService {
private final MyMicroserviceClient myMicroserviceClient;
@Override
public CustomResponse fillList(String idContent, String number) {
CustomResponse response = new CustomResponse();
try {
List<AttachmentDTO> listFiles = new ArrayList<>();
AttachmentDTO attachmentDTO;
AttachmentList pdfList = myMicroserviceClient.getDocsByName(idContent, "*.pdf"); // CALL ONE
log.info("Size: " + pdfList.getattachments().size()); // HERE NullPointerException!!!
for (Attachment attachment : pdfList.getAttachments()) {
attachmentDTO = new AttachmentDTO();
// Some Logic to add attachment to listFiles
}
myMicroserviceClient.processList(listFiles); // CALL TWO
response.setQtySent(listFiles.size());
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
}
My Service Testing file file.
MyServiceSpec
class
class MyServiceSpec extends Specification {
private MyService myService
private MyMicroserviceClient myMicroserviceClient
void setup() {
myMicroserviceClient = Mock(MyMicroserviceClient)
myService = new MyServiceImpl(myMicroserviceClient)
}
def "FillList"() {
given:
def idContent = "0000"
def attachment = Attachment.builder()
.idContent("idContent")
.name("name")
.bytes("bytes".bytes)
.build()
def attachmentList = AttachmentList.builder()
.attachments([attachment])
.build()
myMicroserviceClient.getDocsByName(idContent, "*.pdf") >> attachmentList // HERE my Stub!!!
//Prevent Launch exception
myMicroserviceClient.processList(_ as List<AttachmentDTO>) >> {}
when:
CustomResponse response = myService.fillList(_ as String, number)
// https://jakubdziworski.github.io/java/groovy/spock/2016/05/14/spock-cheatsheet.html
// then: "Only one"
// 1 *
// then: "At least one"
// (1.._) * msCasosClienteNegClient.obtenerDocumentoBinario(_ as String)
// then: "At most"
// (_..1) *
}
}
In the MyMicroserviceClientImpl
class I'm calling the method exchange
of RestTemplate
, as you can see, I have a ParameterizedTypeReference
List
.
In my MyServiceSpec
Service Testing file I try to Stub the call getDocsByName
(check the line with the comment // HERE my Stub!!!
) of the Client, marked in my service CALL ONE
.
When I run my test, I get NullPointerException
in MyServiceImpl
. I think happens that because I need to Stub restTemplate.exchange(...)
too, but I don't know how to do it.
What Would be happening? and How to solve it?. Please some clue...
I think you mixed up two lines.
myMicroserviceClient.getDocsByName(idContent, "*.pdf") >> attachmentList
in the stub call you use the real idContent
CustomResponse response = myService.fillList(_ as String, number)
in this actual service all you are using a wildcard expression _ as String
instead of the real idContent
Also number
is undefined
Try this:
def "FillList"() {
given:
def idContent = "0000"
def attachment = Attachment.builder()
.idContent("idContent")
.name("name")
.bytes("bytes".bytes)
.build()
def attachmentList = AttachmentList.builder()
.attachments([attachment])
.build()
def number = '42'
when:
CustomResponse response = myService.fillList(idContent, number)
then:
1 * myMicroserviceClient.getDocsByName(idContent, "*.pdf") >> attachmentList
}