使用JMock模拟同一类中方法失败,请求技术支持
问题分析
你遇到的核心问题是没有正确处理同一类内部方法的Mock逻辑:
- 你同时创建了真实的
CheckImpl实例check和Mock的CheckImpl实例checkImpl,但实际执行业务逻辑的是真实的check对象,它调用的是自身的newId()方法,完全和你Mock的checkImpl没关系。 - JMock默认创建的是完整Mock对象,而你需要的是部分Mock:让真实对象的特定方法(这里是
newId())被Mock,其他方法保持真实逻辑。
解决方案
下面是修正后的测试代码,关键是使用JMock的部分Mock来处理真实的CheckImpl实例,而不是单独创建一个Mock对象:
public final JUnitRuleMockery mock = new ClassMockery(); private CheckImpl check; private IdDao daoMock; @Before public void setUp() { // 创建真实的CheckImpl实例 check = new CheckImpl(); // Mock IdDao并注入到真实实例中 daoMock = mock.mock(IdDao.class); // 这里如果CheckImpl没有setter,可以用反射注入,或者调整类提供setter check.idDao = daoMock; } @Test public void mainLogic() { String empId = "123"; // 你期望返回的ID List<Id> idList = new ArrayList<>(); // 按你的业务逻辑初始化 mock.checking(new ExtendedExpectations() { { // 对真实的check对象进行部分Mock,指定newId()方法的返回值 oneOf(check).newId(); will(returnValue(empId)); // 验证IdDao的insert方法调用 oneOf(daoMock).insert(with(any(List.class))); will(returnValue(new int[] { 1 })); } }); // 执行真实对象的业务方法 check.MainLogic(idList); }
同时,你的CheckImpl类里的MainLogic方法需要修正语法问题:
public class CheckImpl { @Resource private IdDao idDao; // 加上private修饰符,符合编码规范 public String newId() { // 原业务逻辑,测试时会被Mock覆盖 return String.valueOf(/* 原id生成逻辑 */); } // 修正方法签名,补充参数类型和返回值定义 public List<Id> MainLogic(List<Id> inputList) { List<Id> listInsert = new ArrayList<>(inputList); String s = newId(); // 根据你的Id类构造逻辑调整,这里假设支持String参数构造 listInsert.add(new Id(s)); idDao.insert(listInsert); return listInsert; } }
关键要点
- 部分Mock的使用:JMock通过直接对真实对象指定方法的Mock逻辑,实现部分Mock,这样真实对象执行时会调用Mock的
newId(),其他业务逻辑保持真实。 - 避免多个实例混淆:不要同时创建真实对象和Mock对象,确保执行逻辑的实例就是你做了部分Mock的那个。
- 依赖注入正确:确保Mock的
IdDao正确注入到真实的CheckImpl实例中,这样业务逻辑里的idDao.insert()才会调用Mock方法。
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

