Rhino Mocks:如何在无参数方法中模拟数据库调用?

Rhino Mocks: How to Mock a Database call in a Parameterless Method?

我正在使用 NUnit 和 Rhino Mocks 在 C# 中为 ASP.NET MVC 应用程序编写单元测试。我在测试此方法时遇到了一些问题:

public void Install()
    {
        Database.SetInitializer<DraftOrderObjectContext>(null);
        var dbScript = CreateDatabaseInstallationScript();

        Database.ExecuteSqlCommand(dbScript);
        SaveChanges();
    }

澄清一下,数据库不是指本地对象。第一个"Database.SetInitializer..."指的是:

System.Data.Entity.Database

第二个"Database.ExecuteSqlCommand..."指的是:

System.Data.Entity.DbContext.Database

由于该方法没有 return 任何东西,我认为制作一个模拟并验证 Database.ExecuteSqlCommand(dbScript); 就足够了;至少被调用一次。

现在我以前做过这个,但是涉及将数据库上下文传递给方法,这很容易模拟,但是,在这种情况下没有参数。我需要以某种方式找到一种方法来模拟 'Database'.


我试过像这样直接分配模拟:

System.Data.Entity.DbContext.Database = MockRepository.GenerateMock<System.Data.Entity.DbContext.Database>();

但这会破坏语法,因为 属性 是只读的。


我也试过像这样模拟 DbContext:

System.Data.Entity.DbContext instance = MockRepository.GenerateMock<System.Data.Entity.DbContext>();

        instance.Expect(someCaller => someCaller.Database.ExecuteSqlCommand("sql"))
            .IgnoreArguments()
            .Return(1)
            .Repeat.Times(1);

但我收到一个运行时错误,提示 DbContext.getHashCode() 必须 return 一个值。然后我尝试对 getHashCode 方法进行存根以使其成为 return 但没有效果。


我对模拟还很陌生,所以我可能在这里遗漏了一些基本概念。如果是这样,我深表歉意。非常感谢任何帮助!

恐怕这里唯一值得给出的答案是必须修改代码以使其更易于测试。尝试为调用 static 类、属性或方法的方法编写单元测试不是一项有益或有价值的任务。您建议您可能在这里遗漏了一个基本概念,可能就是这样:static 是单元测试的最大敌人,集体智慧是,投入大量精力测试使用静态的东西没有多大意义资源。只需重构代码即可。

如果重构代码真的不可能,那你为什么要对它进行单元测试(这不是反问,请评论)?如果担心您需要将这些对象作为其他测试的一部分进行模拟,那么您应该使用测试友好界面包装邪恶的、不可修改的代码,然后模拟它。