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
是单元测试的最大敌人,集体智慧是,投入大量精力测试使用静态的东西没有多大意义资源。只需重构代码即可。
如果重构代码真的不可能,那你为什么要对它进行单元测试(这不是反问,请评论)?如果担心您需要将这些对象作为其他测试的一部分进行模拟,那么您应该使用测试友好界面包装邪恶的、不可修改的代码,然后模拟它。
我正在使用 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
是单元测试的最大敌人,集体智慧是,投入大量精力测试使用静态的东西没有多大意义资源。只需重构代码即可。
如果重构代码真的不可能,那你为什么要对它进行单元测试(这不是反问,请评论)?如果担心您需要将这些对象作为其他测试的一部分进行模拟,那么您应该使用测试友好界面包装邪恶的、不可修改的代码,然后模拟它。