У меня проблема с тестированием службы с помощью Spock и Groovy. Для этого я пытаюсь заглушить метод моего клиента, который вызывает RestTemplate
с ParameterizedTypeReference
.
ПРИМЕЧАНИЕ. Извините за мой громоздкий код!!!
Вот мой класс конфигурации
Класс MyMicroserviceClientConfiguration
@Data
@Configuration
@ConfigurationProperties(prefix = "clients.my-microservice-client")
public class MyMicroserviceClientConfiguration {
@NotBlank
private String urlDocsByName;
@NotBlank
private String urlSend;
}
Здесь статические классы
Класс вложения
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class Attachment {
private String idContent;
private String name;
private byte[] bytes;
}
Класс AttachmentList
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class AttachmentList {
private List<Attachment> attachments;
}
Вот мой клиентский класс
MyMicroserviceClientImpl
класс
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();
}
}
}
Другие классы
Класс CustomResponse
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CustomResponse {
private String nameDocument;
private String code;
private int qtySent;
}
Класс AttachmentDTO
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class AttachmentDTO {
@JsonProperty("typeDocument")
private String typeDocument;
@JsonProperty("name")
private String name;
@JsonProperty("base64Content")
private String base64Content;
}
Мой класс обслуживания
MyServiceImpl
класс
@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.
MyServiceSpec
класс
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) *
}
}
В классе MyMicroserviceClientImpl
я вызываю метод exchange
из RestTemplate
, как видите, у меня есть ParameterizedTypeReference
List
.
В моем MyServiceSpec
файле Тестирования Сервиса я пытаюсь Заглушить вызов getDocsByName
(проверьте строку с комментарием // HERE my Stub!!!
) Клиента, отмеченного в моем сервисе CALL ONE
.
Когда я запускаю свой тест, я получаю NullPointerException
в MyServiceImpl
. Я думаю, так бывает, потому что мне тоже нужно Stub restTemplate.exchange(...)
, но я не знаю, как это сделать.
Что будет происходить? и как это решить?. Пожалуйста, подсказку...
Я думаю, вы перепутали две строки.
myMicroserviceClient.getDocsByName(idContent, "*.pdf") >> attachmentList
в вызове-заглушке вы используете настоящий idContent
CustomResponse response = myService.fillList(_ as String, number)
в этом актуальном сервисе вы используете подстановочное выражение _ as String
вместо настоящего idContent
Также number
не определено
Попробуй это:
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
}