我正在使用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
由于该方法没有返回任何内容,我认为做一个mock并验证Database.ExecuteSqlCommand(dbScript)就足够了;被称为至少一次。
现在我已经完成了这个,但是这涉及将数据库上下文传递给方法,这很容易模拟,但是,在这种情况下没有参数。我需要以某种方式找到一种模拟'数据库'的方法。
我已经尝试过像这样直接分配一个模拟:
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()必须返回一个值。然后我尝试将getHashCode方法存根,使其返回一些但没有效果的东西。
我仍然相当嘲笑,所以我可能会错过一些基本概念。如果是这样,我道歉。非常感谢任何帮助!
答案 0 :(得分:1)
我担心唯一值得给出的答案是必须修改代码以使其更加适合测试。尝试为调用 let inputData:Data = "{\"data\": [{\"id\":\"x\"},{\"id\":\"y\"},{\"id\":\"z\"}]}".data(using: .utf8)!
if let response = try JSONSerialization.jsonObject(with: inputData, options: []) as? [String:AnyObject],
let responseData = response["data"] as? [AnyObject]
{
for (index, item) in responseData.enumerated()
{
let id = item["id"] as! String
print(id)
}
}
类,属性或方法的方法编写单元测试并不是一项有益或有价值的任务。你建议你可能在这里错过了一个基本概念,这可能是它:static
是单位测试的最大敌人,集体智慧是没有太多的努力付出很多努力测试使用静态资源的东西。只需重构代码。
如果重构代码真的不可能,那你为什么需要对它进行单元测试(这不是一个修辞问题,请评论)?如果担心你需要在其他测试中模拟这些对象,那么你应该用一个测试友好的界面包装邪恶的,不可修改的代码,然后嘲笑它。