你如何模拟你的存储库?

时间:2008-12-11 15:08:53

标签: testing repository-pattern mocking

我使用Moq模仿我的repositories。但是,最近有人说他们更喜欢创建存储库接口的硬编码测试实现。

每种方法的优点和缺点是什么?

编辑澄清了与Fowler链接的存储库的含义。

3 个答案:

答案 0 :(得分:6)

我通常会看到两个带存储库的方案。我要求一些东西,我得到它,或者我要求一些东西,它就不存在了。

如果您正在模拟您的存储库,那意味着您正在使用您的存储库来测试系统(SUT)。因此,您通常希望在从存储库中获取对象时测试您的SUT是否正常运行。并且你还想测试它是否能够正确地处理这种情况,当你期望得到回报而不是,或者不确定你是否会得到回报。

如果您正在进行集成测试,则硬编码测试双打是可以的。比如说,你想要保存一个对象,然后把它取回来。但这是测试两个对象在一起的交互,而不仅仅是SUT的行为。他们是两个不同的东西。如果您开始编写假存储库,那么您也需要进行单元测试,否则您最终会将代码的成功与失败基于未经测试的代码。

这是我对Mocking vs. Test Doubles的看法。

答案 1 :(得分:6)

SCNR:

“你称自己为存储库?我见过火柴盒的容量更大!”

答案 2 :(得分:0)

我认为“存储库”是指DAO;如果没有,那么这个答案将不适用。

最近我一直在制作“内存”我的DAO的“模拟”(或测试)实现,它基本上是通过传递给mock的构造函数的数据(List,Map等)来操作的。通过这种方式,单元测试类可以自由地输入测试所需的任何数据,可以更改它等,而不必强制对“内存”DAO中运行的所有单元测试进行编码以使用相同的测试数据。

我在这种方法中看到的一个优点是,如果我有十几个单元测试需要使用相同的DAO进行测试(例如注入被测试的类),我不需要记住每次测试数据的所有细节(如果“模拟”是硬编码的那样) - 单元测试自己创建测试数据。在缺点方面,这意味着每个单元测试必须花费几行来创建和连接它的测试数据;但这对我来说是一个小小的缺点。

代码示例:

public interface UserDao {
    User getUser(int userid);
    User getUser(String login);
}

public class InMemoryUserDao implements UserDao {

    private List users;

    public InMemoryUserDao(List users) {
        this.users = users;
    }

    public User getUser(int userid) {
        for (Iterator it = users.iterator(); it.hasNext();) {
            User user = (User) it.next();
            if (userid == user.getId()) {
                return user;
            }
        }

        return null;
    }

    public User getUser(String login) {
        for (Iterator it = users.iterator(); it.hasNext();) {
            User user = (User) it.next();
            if (login.equals(user.getLogin())) {
                return user;
            }
        }

        return null;
    }
}