mockito的模拟限制条件

问题描述:

我得说我是Mockito和TDD的新手..我努力寻找使用它的理由..特别是当我发现像下面这样的问题.. 我想喜欢我的UserService类测试“RegisterUser”方法..我使用Spring MVC的3.0.6,休眠时,Maven等..mockito的模拟限制条件

@Override 
public void registerUser(User user, UserRoles userRole) throws DataAccessException, UserExistingException { 
    checkExistingUser(user); 
    user.addRole(new Role(userRole)); 
    String password = encryptPassword(user); 
    userRepository.makePersistent(user); 
    sendWelcomeEmail(user.getFirstname(), user.getUsername(), password, user.getEmail()); 
} 

private void checkExistingUser(User user) throws UserExistingException { 
    List<User> users = userRepository.findByCriteria(Restrictions.or(Restrictions.eq("username", user.getUsername()), Restrictions.eq("email", user.getEmail()))); 
    if (!CollectionUtils.isEmpty(users)) { 
     User userFound = users.get(0); 
     List<String> fields = new ArrayList<String>(); 
     if (userFound.getUsername().equals(user.getUsername())) { 
      fields.add("username"); 
     } 
     if (userFound.getEmail().equals(user.getEmail())) { 
      fields.add("email"); 
     } 
     throw new UserExistingException(fields); 
    } 
} 

我们测试这个东西,我需要模拟“ userRepository.findByCriteria ..“,我试了下面的junit测试

@Test(expected = UserExistingException.class) 
public void registerExistingUserTest() throws DataAccessException, UserExistingException { 
    User user = new User(); 
    user.setUsername("gfalco77"); 
    user.setEmail("[email protected]"); 
    List<User> users = new ArrayList<User>(); 
    users.add(user); 


    Mockito.when(userRepository.findByCriteria(Restrictions.or(Restrictions.eq("username", user.getUsername()), Restrictions.eq("email", user.getEmail())))).thenReturn(users); 
    userService.registerUser(user, UserRoles.ROLE_USER); 
    Mockito.verify(userRepository).makePersistent(user); 
} 

但似乎”用户“列表总是空的。在之前的文章中,我读到限制不是同一个对象,也许我必须使用Matchers ..但是如何?如果我使用匹配器..它仍然有效创建一个不同的测试?

+0

在你的感情走向的Mockito和TDD:我是相当新的单元测试和TDD自己,但我爱上了JUnit +的Mockito组合几乎是瞬间下降,当我开始使用它 - 这是很容易地进行严格的好方法测试你的代码。我的理解是TDD的一点是,这样的发展模式是为了确保总有您的所有程序的功能测试,让你马上知道你的新的更新打破的东西。这可能不是每个项目的最佳开发模式,但我喜欢牢记这一理念。 –

这不是对您的问题的直接回答,但是您的测试很难编写,因为您的服务类将业务代码与数据访问代码混合在一起。该findByCriteria调用应该被封装到的UserRepository更高级别的方法类似

List<User> findByNameOrEmail(String name, String email) 

你只在你的测试来模拟这种简单的方法,使实际存储库的单元测试,测试的findByNameOrEmail作品预计在测试数据库上。

如果您的UserRepository仅公开诸如findByCriteriafindByQuery等通用方法,那么它不再是真正的存储库,因为条件或查询的创建是由调用者而不是存储库负责的。这样做并没有比直接在业务服务中使用Hibernate会话添加更多的功能。

+0

是的,它是那么明显......现在的工作。该事实是,UserRepository正在伸出GenericHibernateDaoImpl与预定义的findbycriteria ..所以很容易在通过标准.. – Gfalco

+0

这个方法应该加以保护,以服务使其可以由子类调用,但不能由外部类调用。它不应该在存储库的公共界面中。 –