Unit testing doNothing方法不适用于void static方法
我的任务是为一个15年历史的遗留项目添加单元测试代码覆盖率,该项目不使用IoC和0单元测试。我不允许重构代码,因为它在生产环境中工作得非常好,管理层不希望其他团队参与重构,例如QA测试等 服务类有一个Unit testing doNothing方法不适用于void static方法,unit-testing,powermock,Unit Testing,Powermock,我的任务是为一个15年历史的遗留项目添加单元测试代码覆盖率,该项目不使用IoC和0单元测试。我不允许重构代码,因为它在生产环境中工作得非常好,管理层不希望其他团队参与重构,例如QA测试等 服务类有一个performService方法有以下代码 public void performService(requestMessage, responseMessage) { UserAccount userAccount = requestMessage.getUserAccount();
performService
方法有以下代码
public void performService(requestMessage, responseMessage) {
UserAccount userAccount = requestMessage.getUserAccount();
GroupAccount groupAccount = requestMessage.getGroupAccount();
Type type = requestMessage.getType();
StaticServiceCall.enroll(userAccount, groupAccount, type);
response.setStatus(Status.SUCCESS);
}
此StaticServiceCall.enroll
方法正在调用远程服务。我的单元测试是
@RunWith(PowerMockRunner.class)
@PrepareForTest(StaticServiceCall.class)
public class EnrollmentServiceTest {
@Test
public void testPerformService() {
mockStatic(StaticServiceCall.class);
doNothing().when(StaticServiceCall.enroll(any(UserAccount.class), any(GroupAccount.class), any(Type.class)));
service.performService(requestMessage, responseMessage);
assertEquals("Enrollment should be success, but not", Status.SUCCESS, response.getStatus);
}
当类型stuber中的(T)不适用于参数(void)
如果测试代码更改为
mockStatic(StaticServiceCall.class);
doNothing().when(StaticServiceCall.class);
StaticServiceCall.enroll(any(UserAccount.class), any(GroupAccount.class), any(Type.class));
service.performService(requestMessage, responseMessage);
assertEquals("Enrollment should be success, but not", Status.SUCCESS, response.getStatus);
测试用例失败,出现
UnfinishedStubbingException
。我使用的是powermock 1.6.6您对此有一个误解。你认为你需要说doNothing()
什么都不做
这是没有必要的!就像这些线一样
@PrepareForTest(StaticServiceCall.class) ... and
mockStatic(StaticServiceCall.class);
已经足够了
您希望防止在测试期间调用该静态方法时运行该方法的“真实”内容。这就是mockStatic()
正在做的事情
换句话说:只要使用mockStatic(),真正类的完整实现就会被删除。您只需要使用when/then/doReturn/doThrow,以防发生除nothing以外的事情
意思是:只需删除整个doNothing()行 @GhostCat-谢谢你的回答,它解决了问题,我的误解来自这个测试用例
@Test
public void testEnrollmentServiceSuccess() {
RequestMessage requestMessage = new RequestMessage();
requestMessage.setName("ENROLL");
ResponseMessage responseMessage = new ResponseMessage();
EnrollmentService mockService = mock(EnrollmentService.class);
mockService.performService(any(RequestMessage.class), any(ResponseMessage.class));
mockStatic(ClientManager.class);
when(ClientManager.isAuthenticated()).thenReturn(true);
ServiceImpl service = new ServiceImpl();
service.performService(requestMessage, responseMessage);
verify(mockService).performService(any(RequestMessage.class), any(ResponseMessage.class));
}
下面是调用不同服务类的请求消息的基于类的名称的serviceinpl
代码片段
public void performService(RequestMessage request, ResponseMessage response) {
try {
if (request == null) {
throw new InvalidRequestFormatException("null message");
}
if (!ClientManager.isAuthenticated()) {
throw new ServiceFailureException("not authenticated");
}
// main switch for known services
if ("ENROLL".equals(request.getName())) {
service = new EnrollmentService();
service.performService(request, response);
} else if ("VALIDATE".equals(request.getName())) {
...
虽然测试通过,但由于barebone RequestMessage对象,调用了EnrollmentService
中的real实现并引发了异常,然后我搜索了其他内容,再次感谢您的澄清