我被分配为一个15年的遗留项目添加单元测试代码覆盖率,该项目未使用IoC和0单元测试。我不允许重构代码,因为它在生产上完美无缺,管理层不希望其他团队参与重构,如QA测试等。
服务类的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);
}
Eclipse抱怨The method when(T) in the type Stubber is not applicable for the arguments (void)
如果测试代码更改为
,Eclipse会停止抱怨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
答案 0 :(得分:2)
你的结局存在误解。您认为您需要说doNothing()
什么都不做。
这不是必要的!正如这些行
@PrepareForTest(StaticServiceCall.class) ... and
mockStatic(StaticServiceCall.class);
已经足够了。
您希望在测试期间调用方法时阻止运行该静态方法的“真实”内容。这就是mockStatic()
正在做的事情。
换句话说:只要您使用mockStatic(),真实类的完整实现就会被擦除。你只需要使用when / then / doReturn / doThrow,以防你想要发生 else 而不是没有。
含义:只删除整个doNothing()行!
答案 1 :(得分:1)
@GhostCat - 谢谢你的回答,它解决了问题,我的错误观念来自这个测试用例
var globalBus = new Bacon.Bus();
var processBus = new Bacon.Bus();
function startProcess() {
globalBus.push(new Bacon.Next());
}
processBus.skipUntil(globalBus).onValue(function() {
console.log((new Date()).getTime());
});
setInterval(function() {
processBus.push(new Bacon.Next());
}, 1000);
以下是调用不同服务类的请求消息的基于@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));
}
类的名称的代码片段
ServiceImpl
虽然测试通过, 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())) {
...
中的实际实现被调用,并且由于准系统RequestMessage对象而抛出了异常,然后我用google搜索了doNothing,再次感谢您的澄清