Scala中Mock AmazonS3 listObjects方法时ObjectListing设置疑问
解决方案
方法1:使用Mockito直接Mock依赖
这是Scala中最常用的Mock方案,通过MockAmazonS3接口和ObjectListing实例,让方法返回预设结果:
import org.mockito.Mockito._ import com.amazonaws.services.s3.AmazonS3 import com.amazonaws.services.s3.model.{ListObjectsRequest, ObjectListing, S3ObjectSummary} // 初始化Mock对象 val mockS3 = mock(classOf[AmazonS3]) val mockObjectListing = mock(classOf[ObjectListing]) // 构造预设的S3ObjectSummary列表 val testSummaries = List( mock(classOf[S3ObjectSummary]), mock(classOf[S3ObjectSummary]) ) // 设置每个Summary返回指定的Key when(testSummaries(0).getKey).thenReturn("schema_20240501.json") when(testSummaries(1).getKey).thenReturn("schema_20240430.json") // 让Mock的ObjectListing返回预设列表 when(mockObjectListing.getObjectSummaries) .thenReturn(java.util.Arrays.asList(testSummaries:_*)) // 绑定S3客户端的listObjects方法返回Mock的ObjectListing when(mockS3.listObjects(any(classOf[ListObjectsRequest]))) .thenReturn(mockObjectListing) // 将mockS3注入到待测试代码中执行测试逻辑即可
方法2:使用AWS官方Mock客户端
AWS SDK提供了官方测试工具包,包含MockAmazonS3类,可以模拟完整的S3服务行为,无需手动Mock每个方法:
首先在sbt中添加测试依赖:
libraryDependencies += "com.amazonaws" % "aws-java-sdk-test-utils" % "1.12.560" % Test
测试代码示例:
import com.amazonaws.services.s3.model.ListObjectsRequest import com.amazonaws.services.s3.mock.MockAmazonS3 // 创建官方Mock S3客户端 val mockS3 = new MockAmazonS3() // 预先向Mock存储桶中添加测试对象 mockS3.putObject("test-bucket", "schema_20240501.json", "dummy-content") mockS3.putObject("test-bucket", "schema_20240430.json", "dummy-content") // 直接调用listObjects方法,会自动返回包含测试对象的ObjectListing val objects = mockS3.listObjects( new ListObjectsRequest().withBucketName("test-bucket").withMaxKeys(2000) ) // 后续逻辑与待测试代码完全一致,即可得到预期的latestSchemaKey
这种方式更贴近真实S3服务的行为,适合复杂场景的测试,无需关心ObjectListing的内部构造。
方法3:反射修改私有字段(不推荐)
如果上述方案都不适用,可以通过反射修改ObjectListing的私有字段,但这种方式依赖SDK内部实现,版本更新后可能失效:
import com.amazonaws.services.s3.model.{ObjectListing, S3ObjectSummary} import java.util val objectListing = new ObjectListing() val summaries = new util.ArrayList[S3ObjectSummary]() // 添加构造好的S3ObjectSummary到summaries列表 val summary1 = new S3ObjectSummary() summary1.setKey("schema_20240501.json") summaries.add(summary1) // 通过反射设置私有字段 val field = classOf[ObjectListing].getDeclaredField("objectSummaries") field.setAccessible(true) field.set(objectListing, summaries)
内容的提问来源于stack exchange,提问作者Eagleye
相关产品推荐
相关产品推荐

