这是一个非常简单的单元测试用例。
我在类School
中有两种方法:
protected S3Object getAwsObject(AmazonS3Client client, String bucketName, String keyName) {
GetObjectRequest objRequest = new GetObjectRequest(bucketName, keyName);
return client.getObject(objRequest);
}
上述方法由如下所示的第二个方法调用:
public void doTask() {
// get client
AmazonS3Client client = getAwsS3Client();
// invoke the 1st method
S3Object s3Obj = getAwsObject(client, "my-bucket", "my-key");
...
}
我用Mockito来测试方法doTask()
,我试图模拟AmazonS3Client
和存根函数getAwsObject()
:
@Test
public void testDoTask() {
// partially mocked School instance
School school = new School();
School schoolSpy = Mockito.spy(school);
// mock the client & s3 object
AmazonS3Client mockedClient = Mockito.mock(AmazonS3Client.class);
S3Object mockedS3Obj = Mockito.mock(S3Object.class);
Mockito.doReturn(mockedClient)
.when(schoolSpy).getAwsS3Client();
// PROBLEM HERE: I stub function to return mocked S3Object, but real code is run
Mockito.doReturn(mockedS3Obj)
.when(schoolSpy).getAwsObject(mockedClient, "my-bucket", "my-key");
// system under test
schoolSpy.doTask();
}
运行测试时,出现以下错误:
com.amazonaws.services.s3.model.AmazonS3Exception:
The AWS Access Key Id you provided does not exist in our records.
(Service: Amazon S3; Status Code: 403; Error Code: InvalidAccessKeyId; Request ID: 6B973FC095C28524),...
看起来测试用例运行真实的代码client.getObject(objRequest)
而不是使用getAwsObject(...)
的存根,为什么?
如果你没有成功地使你的模拟工作,你可以通过这样覆盖原始方法来解决你的问题:
// mock the client & s3 object
final AmazonS3Client mockedClient = Mockito.mock(AmazonS3Client.class);
final S3Object mockedS3Obj = Mockito.mock(S3Object.class);
School school = new School(){
@Override
protected S3Object getAwsObject(AmazonS3Client client, String bucketName, String keyName) {
return mockedS3Obj;
}
@Override
protected AmazonS3Client getAwsS3Client() {
return mockedClient;
}
};
// system under test
school.doTask();
首先,你不应该使用间谍,而应该在遗留代码中使用。(http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html#spy%28T%29)。如果您委托在非静态工厂/构建器中创建对象,则很容易测试。
但是,在这种情况下,如果 mockito 执行真正的代码,那么你的 doReturn...无效。我认为 Mockito 没有验证参数子句,然后它不会启动 doReturn 子句。
你有
doReturn...getAwsObject(mockedClient, "my-bucket", "my-key")
如果你做下一个并且它有效,那么我是 100% 对的
doReturn...getAwsObject(any(AmazonS3Client.class), anyString(), anyString())
当我在同一语句中使用模拟参数和非模拟参数时,我遇到了问题。 试试这个:
getAwsObject(mockedClient, eq("my-bucket"), eq("my-key"));
如果这不起作用,请尝试使用其他解决方案,例如:
eq(mockedClient), eq(...), eq(...)
最后,如果它不起作用,也许@max解决方案会更容易。
这里做了许多错误的事情。