有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何正确模拟简单的CRUD接口?

假设我有以下简单的示例界面:

public interface UserDB {
    void addUser(User user);
    void updateUser(User user);
    User getUser(String id);
    void deleteUser(String id);
}

我想用Mockito编写测试来测试简单的CRUD操作。我想核实一下:

  • 仅当用户之前使用“添加”添加时,才更新/获取/删除工作
  • 如果用户在使用“删除”之前被删除,则它们将失败
  • 无法再次创建已创建的用户
  • 等等

我的想法是,我需要这样的东西:

    UserDB udb = mock(UserDB.class);
    when(udb.getUser("1")).thenThrow(new UserNotFoundException());
    when(udb.addUser(new User("1"))).when(udb.getUser("1").thenReturn(new User("1"));

然而,像最后一行这样的东西并不是正确的Mockito语法。对于不同的先决条件或调用的方法的不同顺序,我如何检查和验证不同的结果


共 (1) 个答案

  1. # 1 楼答案

    这样做是一种代码气味。事实上,你想写所有这些代码来看看“用户不能被添加两次”实际上只是在写一个新的类,这与你的数据库规则无关

    以下是一个你可以做的事情的想法;将验证规则构造为数据库上的Decorator,然后使用模拟的“未修饰”数据库测试装饰器本身。例如:

    public class ValidatingUserDB implements UserDB {
      private UserDB delegate;
    
      public ValidatingUserDB(UserDB delegate) {
        this.delegate = delegate;
      }
    
      public void addUser(User user) {
        User oldUser = delegate.get(user.getId());
        if (oldUser != null) throw new IllegalArgumentException(
                 "User " + user.getId() + " already exists!";
        delegate.addUser(user);
      }
    }
    

    然后,您可以这样编写测试:

    @Test(expected=IllegalArgumentException.class)
    public void testNoDuplicateUsers() {
      User sampleUser = new User("1");
      UserDB delegate = mock(UserDB.class);
      when(delegate.getUser(any(User.class))).thenReturn(sampleUser);
      UserDB db = new ValidatingUserDB(delegate);
      db.addUser(sampleUser);
    }
    
    public void testAddingUser() {
      User sampleUser = new User("1");
      UserDB delegate = mock(UserDB.class);
      UserDB db = new ValidatingUserDB(delegate);
      db.addUser(sampleUser);
      verify(delegate).getUser(sampleUser);
      verify(delegate).addUser(sampleUser);
    }
    

    通过将验证行为与CRUD行为分离,您可以以一种不需要使用超级复杂的答案规则等重写所有这些测试的方式编写测试