与Mockito嘲笑助手班

时间:2014-12-01 20:34:57

标签: java unit-testing mockito

我有一个普通的帮助器类,其中包含我在服务级别类中使用的公共方法。当我为服务类编写测试并尝试模拟其中一个方法的辅助类时,它将进入方法并运行每一行。由于此方法中的代码更复杂,我想使用方法来模拟辅助类,这样我就不必处理辅助类方法中的每个细节。

服务类

class HistoryServiceImpl implements CaseHistory {
  @Override
  public List<CaseHistoryDto> getCaseHistory(Individual member, Individual provider) {
    MemberUtil memberUtil = new MemberUtil();
    List<CaseHistoryDto> caseHistoryDtoList = new ArrayList<CaseHistoryDto>();
    List<CaseHistory> caseHistoryList = caseDetailDao.fetchCaseHistory(member.getId(), provider.getId());
    for(CaseHistory caseHistory : caseHistoryList) {
        CaseHistoryDto caseHistoryDto = new CaseHistoryDto();
        caseHistoryDto.setMemberInfo(memberUtil.getMemberInfo(member, caseHistory.getCreateDate()));
        caseHistoryDtoList.add(caseHistoryDto);
    }
    return caseHistoryDtoList;
  }
}

测试类

Class HistoryServiceTest {
  @Mock MemberUtil memberUtil;
  @InjectMocks private HistoryServiceImpl historyServiceImpl = new HistoryServiceImpl();

  @Test
  public void testGetCaseHistory() {
    //why this line going inside real method and executing all lines?
    when(memberUtil.getMemberInfo(any(Individual.class), any(Date.class))).thenReturn(member);
  }
}

1 个答案:

答案 0 :(得分:2)

您的测试用例运行&#34; real&#34;中的所有行的原因方法,是因为你的模拟对象永远不会在任何地方使用。

如上所述,您无法在MemberUtil中模拟HistoryServiceImpl,因为您是在getCaseHistory()方法中手动实例化它。您需要让getCaseHistory()从其他地方获取MemberUtil,以便您可以在测试类中注入模拟版本。

最简单的解决方案是将MemberUtil定义为成员变量,以便@InjectMocks注释可以覆盖默认值:

class HistoryServiceImpl implements CaseHistory {
    MemberUtil memberUtil = new MemberUtil();

    @Override
    public List<CaseHistoryDto> getCaseHistory(Individual member, Individual provider) {
        ...
    }
}

或者,您可以HistoryServiceImpl在其构造函数中或通过setter方法接受外部提供的MemberUtil。然后,您可以轻松地在测试类中传入模拟版本。

通常,实用程序类是无状态的,因此另一种可能的解决方案是转换MemberUtil以使其所有方法都是静态的。然后你可以使用类似PowerMock的东西来模拟你的静态方法。