groovy 如何在Spock中模拟一个类的单个方法?

svmlkihl  于 2023-08-02  发布在  其他
关注(0)|答案(3)|浏览(133)

我在我的类中有一个类似下面的方法,我正在尝试测试:

class SomeHelper { 
    ByteArrayOutputStream fooBar (Request request) {
       ByteArrayOutputStream baos = someParser.parseData(getRequestFileInputStream(request.filename))
       return baos
    }
    InputStream getRequestFileInputStream(String filename) {
      //return intputStream of object from S3
    }
....
}

字符串
在上面的例子中,getRequestFileInputStream是一个以文件名作为参数的方法。它从AWS S3获取该文件的输入流。在测试Spock中的fooBar方法时,我想为getRequestFileInputStream方法提供一个mock,因为我不想使用类中的此方法的实现,因为它转到另一个bucket名称。
有可能做到这一点吗?
下面是我尝试过的:

class SomeHelperSpec extends Specification{
    //this is the implementation of getRequestFileInputStream I want to use while testing
    InputStream getObjectFromS3(String objectName) {
            def env = System.getenv()
            AwsClientBuilder.EndpointConfiguration endpoint = new AwsClientBuilder.EndpointConfiguration(env["endpoint_url"], env["region_name"])
            AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard()
            builder.setEndpointConfiguration(endpoint)
            builder.setCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(env["ACCESS_KEY"], env["SECRET_KEY"])))
            AmazonS3 s3 = builder.build()
            return s3.getObject("testbucket", objectName).getObjectContent()

    }

    def "test fooBar" () {
      given: 
         someHelper = new SomeHelper()
         someHelper.getRequestFileInputStream(_) >> getObjectFromS3(fileName)
         someHelper.someParser = Mock(SomeParser) {
           ....
         }
         Request requestInstance = new Request()
         request.filename = fileName
         request.fileType = fileType
      expect:
         someHelper.fooBar(requestInstance).getText == returnVal

      where:
         fileType | fileName      | returnVal    
         "PDF"    | "somepdf.pdf" | "somereturnval"
    }
}


但是,上面的方法不起作用,因为它仍然试图在SomeHelper中调用getRequestFileInputStream的原始实现,而不是使用规范中提供的模拟实现。

sdnqo3pr

sdnqo3pr1#

你可以用间谍

def someHelper = Spy(SomeHelper)
someHelper.getRequestFileInputStream(_) >> getObjectFromS3(fileName)

字符串
见间谍。

sxissh06

sxissh062#

你可以使用一个真实的对象,但要使用覆盖的方法:

given:
    someHelper = new SomeHelper() {
         @Override
         InputStream getRequestFileInputStream(String filename) {
             return getObjectFromS3(fileName)
         }
    }

字符串

mxg2im7a

mxg2im7a3#

作为对任何在这里找到自己的方式的人的说明,您可以将上述两个答案结合起来。您可以提供一个接口的新实现,然后将其 Package 在Spy中。如果您需要实现一个泛型接口并获得正确的类型信息(例如,如果您的代码使用反射魔法),同时仍然进行基于交互的测试,这将非常有用。
举例来说:

given:
def mock = Spy(new MyParameterizedClass<List>() { 
    List someMethod() { 
        return [] 
    } 
})

//...do something that makes your mock get called

expect:
1 * mock.someMethod

字符串

相关问题