You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用MockK模拟S3 PutObject请求?解决匹配失败异常

问题

我有一个将数据上传至S3的函数,代码如下:

val s3Client = S3Client.create()
    
data class S3Object(
     val bucket: String,
     val key: String,
     val contents: String,
     val contentType: String
)
        
 fun putS3Object(s3Object: S3Object){
     val putObjectRequest = PutObjectRequest.builder()
                        .bucket(s3Object.bucket)
                        .key(s3Object.key.toString())
                        .contentType(s3Object.contentType)
                        .build()
     s3Client.putObject(putObjectRequest, RequestBody.fromString(s3Object.contents))
  }

我尝试按如下方式进行模拟:

every { S3Client.create()} returns s3Client

val s3Object = S3Object("test-bucket", "/test/key", "test-event", "application/json; charset=UTF-8")
val putRequest = PutObjectRequest.builder()
            .bucket(s3Object.bucket)
            .contentType(s3Object.contentType)
            .key(s3Object.key)
            .build()
val putObjectResponse = PutObjectResponse
            .builder()
            .build()
every{ s3Client.putObject(putObjectRequest, RequestBody.fromString(s3Object.contents))} answers {putObjectResponse}

运行测试时出现以下MockK异常:

io.mockk.MockKException: no answer found for: S3Client(#4).putObject(PutObjectRequest(Bucket=test-bucket, ContentType=application/json; charset=UTF-8, Key="/test/key"), software.amazon.awssdk.core.sync.RequestBody@49322d04)

解决方法

核心原因

MockK匹配失败是因为你手动创建的putRequest和RequestBody实例,跟被测试函数内部生成的不是同一个对象。MockK默认严格匹配对象实例,因此找不到对应的模拟方法。

具体修复步骤

1. 放宽请求对象的匹配条件

不用固定实例匹配,改用匹配器验证请求的关键属性是否符合预期:

every { 
    s3Client.putObject(
        match { req ->
            req.bucket() == s3Object.bucket &&
            req.key() == s3Object.key &&
            req.contentType() == s3Object.contentType
        },
        any()
    ) 
} returns putObjectResponse

2. 精准验证请求体内容

如果需要确认RequestBody的内容,可添加内容匹配逻辑:

every { 
    s3Client.putObject(
        match { req ->
            req.bucket() == s3Object.bucket &&
            req.key() == s3Object.key &&
            req.contentType() == s3Object.contentType
        },
        match { body ->
            body.asByteArray().contentEquals(s3Object.contents.toByteArray())
        }
    ) 
} returns putObjectResponse

3. 简化匹配(可选)

若不需要验证请求细节,可直接用泛型匹配器简化代码:

every { s3Client.putObject(any<PutObjectRequest>(), any<RequestBody>()) } returns putObjectResponse

额外注意

被测试函数中调用了s3Object.key.toString(),尽管当前测试用例的key是String类型,但如果后续key类型变更,需确保测试与实际逻辑一致,避免行为差异。

内容的提问来源于stack exchange,提问作者CyberPunk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 04:05:21