【问题标题】:Groovy Spock mock calling real method of mocked classGroovy Spock 模拟调用模拟类的真实方法
【发布时间】:2019-08-29 07:54:38
【问题描述】:

我正在尝试为一个使用 Google 视觉 API 和来自 google-cloud-vision 库的 AnnotatorImageClient 的类编写单元测试。 问题是我嘲笑的AnnotatorImageClient 出于某种原因仍然调用真正的batchAnnotateImages 方法,然后抛出一个NPE,这打破了我的测试。 我以前从未在模拟中看到过这种行为,我想知道我是否做错了什么,spock/groovy 中是否存在错误,或者它是否与该 Google 库有关?

我已经检查过我班级中使用的对象是否真的是一个模拟对象,它就是。我试过 Spock 版本 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()
    }
}

我希望 mock 简单地返回 null(我知道这个测试没有多大意义)。相反,它会调用com.google.cloud.vision.v1.ImageAnnotatorClient.batchAnnotateImages,这会引发 NPE。

【问题讨论】:

  • 只用_试试 - 参数_ as List似乎没有正确匹配?
  • 我也用_ 尝试过,但仍然得到相同的结果。即使我完全省略了存根,结果仍然是一样的:调用真正的方法,抛出 NPE。

标签: java groovy mocking spock vision-api


【解决方案1】:

ImageAnnotatorClient是用Java编写的,方法batchAnnotateImages(List&lt;AnnotateImageRequest&gt; requests)final

Spock 能够模拟 Java final 类,但在模拟 Java final 方法方面不太好。

您可以使用PowerMock 来获得您需要的东西,here 是如何与 Spock 一起使用的教程。

【讨论】:

  • 但是可以更改修饰符as in this answer
  • @Jazzschmidt 是的,你是对的,反射是第二个选择。
  • 非常感谢您为我指明了正确的方向! groovy 似乎确实对本身不是最终但包含最终方法的类存在问题。我通过在我的班级和 ImageAnnotatorClient 之间创建一个小外观解决了这个问题,它只是充当代理并且可以被 Spock 毫无问题地模拟。
  • 我在 Kotlin 中遇到过这样的问题,因为该方法没有用关键字“open”标记。这个回复给了我正确的线索 :) 所以如果你使用 kotlin,请留意这一点。
【解决方案2】:

在我的例子中,我必须用 SpringBean 这个导入来注释模拟字段;

import org.spockframework.spring.SpringBean

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-23
    • 2016-03-04
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多