Я пытаюсь написать модульный тест для класса, который использует 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.
Я пробовал это и с _
, но результат все равно тот же. Даже когда я полностью опускаю заглушки, результат остается тем же: вызывается настоящий метод, выбрасывается NPE.
Класс ImageAnnotatorClient
написан на Java, а метод batchAnnotateImages(List<AnnotateImageRequest> requests)
— это final
.
Спок может издеваться над финальными классами Java, но не так хорошо в имитации финальных методов Java.
Вы можете использовать PowerMock, чтобы получить то, что вам нужно, здесь - это руководство, как заставить его работать вместе со Споком.
Но можно было бы изменить модификатор как в этом ответе
@Jazzschmidt да, ты прав, отражение - это второй вариант.
Большое спасибо за то, что указали мне правильное направление! Действительно кажется, что у groovy есть проблема с классами, которые сами по себе не являются окончательными, но содержат окончательные методы. Я решил проблему, создав небольшой фасад между моим классом и ImageAnnotatorClient
, который просто служит прокси-сервером и может без проблем высмеиваться Споком.
У меня была такая проблема в Котлине, потому что метод не был помечен ключевым словом «открыть». Этот ответ дал мне правильную подсказку :) Так что следите за этим, если вы используете kotlin.
В моем случае мне пришлось аннотировать фиктивное поле с помощью этого импорта;
SpringBean
Попробуйте просто
_
- кажется, что параметр_ as List
не соответствует правильно?