上传到 S3 的单元测试

jon*_*ony 4 java junit unit-testing amazon-s3

我在为将文件覆盖到 S3 存储桶的方法编写单元测试时遇到问题。该方法抓取文件的原始元数据,然后用新的修改版本和相同的原始元数据覆盖文件。

我想要什么测试要做的就是核实内方法,如getObjectMetadataputObject用正确的参数调用正确

这是方法:

 public void upload(File file, String account, String bucketName) {
        String key = "fakekey";
        ObjectMetadata objMData = client.getObjectMetadata(bucketName, key).clone();
        try {
            // cloning metadata so that overwritten file has same metadata as original file
            client.putObject(new PutObjectRequest(bucketName, key, file).withMetadata(objMData));
        } catch(AmazonClientException e) {
            e.printStackTrace();
        } 
Run Code Online (Sandbox Code Playgroud)

这是我的测试方法:

@Mock
private AmazonS3 client = new AmazonS3Client();

public void testUpload() {

    S3Uploader uploader = new S3Uploader(client);

    File testFile = new File("file.txt");
    String filename = "file.txt";
    String bucketname = "buckettest";
    String account = "account";

    String key = account+filename;
    ObjectMetadata objMetadata = Mockito.mock(ObjectMetadata.class);
    when(client.getObjectMetadata(bucketname, key).clone()).thenReturn(objectMetadata);

    // can I make this line do nothing? doNothing()??
    doNothing.when(client.putObject(Matchers.eq(new PutObjectRequest(bucketName, key, file).withMetadata(objMData))));

    uploader.upload(aFile, anAccount, bucketName);

    // how do I verify that methods were called correctly??
    // what can I assert here?

}
Run Code Online (Sandbox Code Playgroud)

NullPointerException在测试中 得到了结果

when(client.getObjectMetadata(bucketname, key).clone()).thenReturn(objectMetadata);
Run Code Online (Sandbox Code Playgroud)

我什至无法访问方法调用。老实说,我非常想问的是,我如何验证这种upload()方法是否正确?

gly*_*ing 7

您在问题中展示的方法使用一个client实例与 S3 对话。client此方法所属的类中的实例要么被注入(例如在构造时),要么被创建(可能通过工厂)。假设它是在创建包含类时注入的,那么您的测试用例可能如下所示:

@Test
public void testSomething() {
    AmazonS3 client = Mockito.mock(AmazonS3.class);

    S3Uploader uploader = new S3Uploader(client);

    String bucketName = "aBucketName";

    // ensures that the getObjectMetadata call fails thereby throwing the exception which your method catches
    Mockito.when(client.getObjectMetadata(Matchers.eq(bucketName), Matchers.eq("fakekey")).thenThrow(new AmazonServiceException());

    uploader.uploadToS3(aFile, anAccount, bucketName);

    // at this stage you would typically assert that the response 
    // from the upload invocation is valid but as things stand 
    // upload() swallows the exception so there's nothing to assert against
}


@Test
public void testSomethingElse() {
    AmazonS3 client = Mockito.mock(AmazonS3.class);

    S3Uploader uploader = new S3Uploader(client);

    String bucketName = "aBucketName";
    String key = "fakekey";
    File aFile = ...;
    ObjectMetadata objMData = ...;

    // ensures that the getObjectMetadata call succeeds thereby allowing the call to continue to the subsequent putObject invocation
    Mockito.when(client.getObjectMetadata(eq(bucketName), eq(key)).thenReturn(objMData);

    // ensures that the putObject call fails thereby throwing the exception which your method catches
    Mockito.when(client.putObject(Matchers.eq(new PutObjectRequest(bucketName, key, file).withMetadata(objMData)).thenThrow(new AmazonServiceException());

    uploader.uploadToS3(aFile, anAccount, bucketName);

    // at this stage you would typically assert that the response 
    // from the upload invocation is valid but as things stand 
    // upload() swallows the exception so there's nothing to assert against
}
Run Code Online (Sandbox Code Playgroud)

上面的代码使用Mockito来模拟 AmazonS3 客户端,这允许您调整client实例的行为,以便您的测试调用沿着“抛出异常”路径进行。

在一个侧面说明catch子句看,因为有些奇怪AmazonS3.putObject,并AmazonS3.getObjectMetadata都宣称抛出AmazonServiceExceptionAmazonServiceException延伸AmazonClientException


ron*_*ash 1

我建议您使用这个项目https://github.com/findify/s3mock。创建 S3 存储桶的模拟,然后您可以测试当您查找的存储桶存在或不存在时会发生什么。