Groovy Spock имитирует вызов реального метода издевательского класса

Я пытаюсь написать модульный тест для класса, который использует API видения Google с AnnotatorImageClient из библиотеки google-cloud-vision. Проблема в том, что мой издевательский AnnotatorImageClient по какой-то причине все еще вызывает настоящий batchAnnotateImages метод, а затем выдает NPE, что ломает мой тест. Я никогда раньше не видел такого поведения на макете, и мне интересно, делаю ли я что-то не так, есть ли ошибка в spock/groovy или это как-то связано с этой библиотекой Google?

Я уже проверил, действительно ли объект, используемый в моем классе, является макетом, и это так. Я пробовал со Споком версии 1.2-groovy-2.5 и 1.3-groovy.2.5.

Тестируемый класс:

public class VisionClient {

    private final ImageAnnotatorClient client;

    @Autowired
    public VisionClient(final ImageAnnotatorClient client) {
        this.client = client;
    }

    public Optional<BatchAnnotateImagesResponse> getLabelsForImage(final Image image) {
        var feature = Feature.newBuilder().setType(LABEL_DETECTION).build();

        var request = AnnotateImageRequest.newBuilder()
                .addFeatures(feature)
                .setImage(image)
                .build();

        return Optional.ofNullable(client.batchAnnotateImages(singletonList(request)));
}

Тест:

class VisionClientSpec extends Specification {
    def "The client should use Google's client to call Vision API"() {
        given:
        def googleClientMock = Mock(ImageAnnotatorClient)
        def visionClient = new VisionClient(googleClientMock)
        def imageMock = Image.newBuilder().build()

        when:
        def resultOpt = visionClient.getLabelsForImage(imageMock)

        then:
        1 * googleClientMock.batchAnnotateImages(_ as List) >> null
        !resultOpt.isPresent()
    }
}

Я бы ожидал, что макет просто вернется null (я знаю, что этот тест не имеет большого смысла). Вместо этого он вызывает com.google.cloud.vision.v1.ImageAnnotatorClient.batchAnnotateImages, который выдает NPE.

Попробуйте просто _ - кажется, что параметр _ as List не соответствует правильно?

Opal 08.04.2019 10:56

Я пробовал это и с _, но результат все равно тот же. Даже когда я полностью опускаю заглушки, результат остается тем же: вызывается настоящий метод, выбрасывается NPE.

Roman Abendroth 08.04.2019 11:06
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
2
2 818
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Класс ImageAnnotatorClient написан на Java, а метод batchAnnotateImages(List<AnnotateImageRequest> requests) — это final.

Спок может издеваться над финальными классами Java, но не так хорошо в имитации финальных методов Java.

Вы можете использовать PowerMock, чтобы получить то, что вам нужно, здесь - это руководство, как заставить его работать вместе со Споком.

Но можно было бы изменить модификатор как в этом ответе

Jazzschmidt 08.04.2019 12:28

@Jazzschmidt да, ты прав, отражение - это второй вариант.

Dmytro Patserkovskyi 08.04.2019 12:31

Большое спасибо за то, что указали мне правильное направление! Действительно кажется, что у groovy есть проблема с классами, которые сами по себе не являются окончательными, но содержат окончательные методы. Я решил проблему, создав небольшой фасад между моим классом и ImageAnnotatorClient, который просто служит прокси-сервером и может без проблем высмеиваться Споком.

Roman Abendroth 12.04.2019 08:27

У меня была такая проблема в Котлине, потому что метод не был помечен ключевым словом «открыть». Этот ответ дал мне правильную подсказку :) Так что следите за этим, если вы используете kotlin.

Lucas Andrade 26.03.2021 15:04

В моем случае мне пришлось аннотировать фиктивное поле с помощью этого импорта;

SpringBean

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