Mockito+JUnit4 Mock方法未生效:调用实际方法问题求助
我正在学习Mockito与JUnit4,现有UserService接口及其实现类UserServiceImpl,在UserInfoImpl类中调用了该接口的getUserInfo方法。尝试通过Mock UserServiceImpl来测试UserInfoImpl,但实际调用的是真实方法(已通过真实方法中的System.out验证),不清楚原因,请求技术支持。
相关代码
JUnit测试类
public class Junit4WithMockito { private UserInfoImpl userInfo; @Mock private UserService userService; @Before public void setUp() { System.out.println("Inside Setup"); MockitoAnnotations.initMocks(this); } @Test public void testUserInfoImpl() throws InterruptedException { String cid="yu444"; userInfo = new UserInfoImpl(); userInfo.setUserService(userService); when(userService.getUserInfo(cid)).thenReturn(new User("John Doe",33)); Assert.assertEquals("Peter",userInfo.getUserInfo(cid).getUsername()); } }
UserInfoImpl类
public class UserInfoImpl implements UserInfo { private UserService userService; public UserService getUserService() { return userService; } public void setUserService(UserService userService) { this.userService = userService; } @Override public User getUserInfo(String username) { try { userService = new UserServiceImpl(); return userService.getUserInfo(username); } catch (InterruptedException e) { e.printStackTrace(); return null; } } }
UserServiceImpl类
public class UserServiceImpl implements UserService { @Override public User getUserInfo(String username) throws InterruptedException { System.out.println("Inside the actual Service"); Thread.sleep(5000); return new User("John Doe",33); } }
错误信息

原因分析
核心问题出在UserInfoImpl的getUserInfo方法中:你在方法内部手动创建了UserServiceImpl实例,覆盖了通过setUserService注入的Mock对象。也就是说,测试代码中你先通过userInfo.setUserService(userService)把Mock对象注入到userInfo中,但当执行userInfo.getUserInfo(cid)时,方法内部的userService = new UserServiceImpl();语句直接替换掉了之前的Mock实例,导致实际调用的是真实服务类的方法。
解决方案
修改UserInfoImpl的getUserInfo方法,移除内部创建UserServiceImpl的代码,直接使用已注入的userService实例:
public class UserInfoImpl implements UserInfo { private UserService userService; public UserService getUserService() { return userService; } public void setUserService(UserService userService) { this.userService = userService; } @Override public User getUserInfo(String username) { try { // 移除手动创建实例的代码,直接使用注入的userService return userService.getUserInfo(username); } catch (InterruptedException e) { e.printStackTrace(); return null; } } }
额外说明
修改后,测试类中的Mock配置会生效,但当前测试代码中的断言Assert.assertEquals("Peter",userInfo.getUserInfo(cid).getUsername())会失败,因为你预设的返回值是new User("John Doe",33),需要将断言调整为Assert.assertEquals("John Doe",userInfo.getUserInfo(cid).getUsername()),或者修改预设的返回值为new User("Peter",xxx)。
内容的提问来源于stack exchange,提问作者Saimuga

