Метод Stub Rest Client, вызывающий RestTemplate с ParameterizedTypeReference для службы тестирования

У меня проблема с тестированием службы с помощью 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, как видите, у меня есть ParameterizedTypeReferenceList.

В моем MyServiceSpec файле Тестирования Сервиса я пытаюсь Заглушить вызов getDocsByName (проверьте строку с комментарием // HERE my Stub!!!) Клиента, отмеченного в моем сервисе CALL ONE.

Когда я запускаю свой тест, я получаю NullPointerException в MyServiceImpl. Я думаю, так бывает, потому что мне тоже нужно Stub restTemplate.exchange(...), но я не знаю, как это сделать.

Что будет происходить? и как это решить?. Пожалуйста, подсказку...

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, вы перепутали две строки.

  • 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
    }

Другие вопросы по теме