Scala替换AmazonS3客户端后单元测试403权限问题的解决
问题解决:Mock AmazonS3 时出现403 Access Denied的处理方案
问题背景
将S3Repository类的uploadCsvToS3方法中已弃用的AmazonS3Client替换为AmazonS3,通过AmazonS3ClientBuilder构建客户端并调用putObject方法,业务功能运行正常,但单元测试阶段出现异常:
- 测试中已Mock
AmazonS3客户端并通过Guice绑定 - 设置Mockito预期返回
PutObjectResult,但执行测试时抛出**Access Denied(403)**错误 - 尝试配置密钥、PowerMockito等方案均无效
问题代码
业务实现代码
val creds = DefaultAWSCredentialsProviderChain.getInstance() val awsRegion: Regions = Regions.fromName(configuration.get[String]("aws.s3.region")) val client: AmazonS3 = AmazonS3ClientBuilder.standard().withRegion(awsRegion).withCredentials(creds).build() val fileName = produceFileNameForVersion(params_to_this_method) client.putObject(AWSS3Bucket, fileName, file.toFile)
单元测试代码
val client = mock[AmazonS3] override def fakeApplication(): Application = new GuiceApplicationBuilder() .overrides(bind[AmazonS3].toInstance(client)) Mockito.when(client.putObject(MockitoMatchers.eq(s3Bucket), MockitoMatchers.anyString(), MockitoMatchers.eq(file))) thenReturn new PutObjectResult val s3Repository : S3Repository = app.injector.instanceOf[S3Repository] val s3Location = s3Repository.uploadCsvToS3(file.toPath).futureValue assert(s3Location.fileName.nonEmpty)
解决方案
问题根源是业务代码直接在方法内实例化AmazonS3客户端,导致Guice绑定的Mock实例无法被注入,实际调用的是真实AWS客户端,从而触发403权限错误。
通过创建AmazonS3ClientProvider类封装客户端实例化逻辑,再通过Guice绑定该Provider,让业务代码通过依赖注入获取客户端,确保测试时Mock实例能被正确注入。
关键绑定配置
bind(classOf[AmazonS3]).toProvider(classOf[AmazonS3ClientProvider])
调整后的业务代码思路
将客户端实例化逻辑移到Provider中,业务类通过构造函数注入AmazonS3实例:
class S3Repository @Inject()(amazonS3: AmazonS3, configuration: Configuration) { def uploadCsvToS3(filePath: Path): Future[S3Location] = { val fileName = produceFileNameForVersion(params_to_this_method) amazonS3.putObject(AWSS3Bucket, fileName, filePath.toFile) // 后续业务逻辑... } }
AmazonS3ClientProvider示例
class AmazonS3ClientProvider @Inject()(configuration: Configuration) extends Provider[AmazonS3] { override def get(): AmazonS3 = { val creds = DefaultAWSCredentialsProviderChain.getInstance() val awsRegion: Regions = Regions.fromName(configuration.get[String]("aws.s3.region")) AmazonS3ClientBuilder.standard().withRegion(awsRegion).withCredentials(creds).build() } }
修改后,单元测试中Guice绑定的MockAmazonS3实例会被正确注入到S3Repository中,避免调用真实AWS服务,解决403错误。
内容的提问来源于stack exchange,提问作者Nili Al
相关产品推荐
相关产品推荐

