在 junit 测试中,当被测类直接调用返回 void 的 `s3client.deleteobject()` 方法时,不能使用 `when(...).thenreturn(...)`,而应改用 `donothing().when(...).method()` 进行行为模拟,从而安全跳过该行执行。
在使用 Mockito 对 AWS SDK(如 AmazonS3)进行单元测试时,一个常见误区是试图对 void 方法使用 when().thenReturn() 语法。由于 deleteObject(DeleteObjectRequest) 是一个无返回值方法(即返回类型为 void),Mockito 的 when() API 无法为其建立 stub —— 它专为有返回值的方法设计,因此编译器会报错:
error: no instances of type variable T exist so that void conforms to T
✅ 正确做法是使用 doNothing() 配合 when() 的变体语法(即 doNothing().when(mock).voidMethod()),它专为 void 方法设计,用于声明“调用该方法时不执行任何操作”。
// 创建 mock 实例
AmazonS3 s3Client = mock(AmazonS3.class);
// 告诉 Mockito:当 deleteObject 被任意 DeleteObjectRequest 调用时,什么也不做
doNothing()
.when(s3Client)
.deleteObject(any(DeleteObjectRequest.class));⚠️ 注意事项:
class MyClassTest {
@Mock
private AmazonS3 s3Client;
@InjectMocks
private MyC
lass myClass; // 假设 MyClass 构造函数或字段接受 AmazonS3
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
void myMethod_deletesObjectInS3_whenCalled() {
// Arrange
doNothing()
.when(s3Client)
.deleteObject(any(DeleteObjectRequest.class));
// Act
myClass.myMethod("test-bucket", "path/to/object");
// Assert(可选:验证是否确实调用了该方法)
verify(s3Client).deleteObject(argThat(req ->
"test-bucket".equals(req.getBucketName()) &&
"path/to/object".equals(req.getKey())
));
}
}? 总结:对 void 方法打桩,请始终优先使用 doNothing().when(mock).method();避免 when(mock.method()).thenReturn(...)(编译失败)或 when(mock.method()).thenThrow(...)(语法非法)。这是 Mockito 的核心约定,也是编写可靠、可维护单元测试的关键实践。