2013-06-27 73 views
2

所以我想为我的业务逻辑层写一些测试用例。我已经嘲笑了我的数据访问层(它返回NHibernate IQueryOver对象)。我创建了一个MockQueryOver类,它实现了IQueryOver接口,因为我在业务逻辑层中链接函数,因此创建存根IQueryOver对我来说没有意义。模拟NHibernate的IQueryOverOrderBuilder对象

无论如何,这是所有的作品,但我遇到的问题是当我尝试在QueryOver上做一个OrderBy()。在我MockQueryOver类,我实现OrderBy()方法像现在这样的权利:

public IQueryOverOrderBuilder<TRoot, TSubType> OrderBy(Expression<Func<TSubType, object>> path) 
{ 
    var func = path.Compile(); 
    IList<TSubType> result = m_data.OrderBy(func).ToList(); 
    var mockRepo = new MockRepository(); 
    var queryOver = new MockQueryOver<TRoot, TSubType>(m_data); 

    IQueryOverOrderBuilder<TRoot, TSubType> mockOrderBuilder = mockRepo.StrictMock<IQueryOverOrderBuilder<TRoot, TSubType>>(queryOver, path); 
    mockOrderBuilder.Stub(x => x.Desc).Return(queryOver); 
    mockOrderBuilder.Stub(x => x.Asc).Return(queryOver); 

    return mockOrderBuilder; 
} 

的问题是,RhinoMocks抛出任何的stub方法例外。这是个例外:

System.NullReferenceException : Object reference not set to an instance of an object. 
at NHibernate.Criterion.Lambda.QueryOverOrderBuilderBase`3.AddOrder(Func`2 orderStringDelegate, Func`2 orderDelegate) 
at NHibernate.Criterion.Lambda.QueryOverOrderBuilderBase`3.get_Desc() 
at NHibernate.Criterion.QueryOverBuilderExtensions.Desc(IQueryOverOrderBuilder`2 builder) 
at BLL.Tests.Mock_Objects.MockQueryOver`2.<OrderBy>b__7(IQueryOverOrderBuilder`2 x) in MockQueryOverSubType.cs: line 239 

我是新来NHibernate和RhinoMocks,所以我不知道它在做什么在幕后,但似乎即使我创建的接口的模拟,当我尝试存根方法时仍然调用具体的扩展方法。

有人可以澄清这一点或帮助我解决这个问题吗?另外,因为我刚刚开始编写这些测试用例,所以我不介意改用模拟框架,只要它可以自由使用。

非常感谢!

回答

3

你确定IQueryOverOrderBuilder是一个界面?它似乎是a confusingly-named class that implements QueryOverOrderBuilderBase。我并不完全确定这种情况下的行为,但我认为您的StrictMockIQueryOverOrderBuilder实际上是通过调用该基类来实现的,该基类可能没有设置,并且抛出了您所看到的异常。

我认为也许你可能需要在业务逻辑和NHibernate之间添加另一个抽象层,并且你可以可靠地模拟类。我不认为有一种嘲讽像RhinoMocks IQueryOverOrderBuilder具体类的方式(但我很乐意被纠正,如果有:)。

要创建另一个抽象层,分析当前与NHibernate交互的业务逻辑中的操作,并定义一个新的函数接口来封装这些操作(比如IRepository)。通过NHibernate向数据库添加内容的代码可能会成为名为AddItem的接口上的一个函数。将与该接口背后的NHibernate交互的代码移动到新类的新函数中(没有理由说它需要成为一个类 - 您可以将逻辑相关的代码组合成具有不同接口的独立类)。新的接口可能能够引用一些NHibernate类和接口,这些类和接口可以很容易地实例化或模拟(理想情况下,接口根本不会引用NHibernate,但是这样做是为了测试,而不是完全解耦你的代码来自NHibernate,所以没关系)。一旦你完成了这个工作,你的业务逻辑就可以针对新接口的模拟(或模拟)进行单元测试,并且实现该接口的类或类可以针对实际数据库进行集成测试。这是松散的,Adapter pattern。如果没有确切地看到你的业务逻辑如何,就很难对设计进行进一步评论。我希望这是有帮助的。

最后,如果你创建自己的MockRepository,我认为你需要调用您创建的嘲笑Replay()(或ReplayAll()MockRepository)你存根后他们。如果您使用MockRepository上的静态方法创建模拟,则无需执行此操作。似乎与你目前的问题无关(尽管在你拨打Stub后打电话询问它是否有任何区别),但我想我会提及它。

+0

是的,你是正确的,它是一个名为接口的具体类。你能否给我一个关于如何创建一个中间层的基本例子?我不确定我能做什么。 –

+0

我在业务逻辑和NHibernate之间添加了更多关于创建抽象层的细节。我希望这是清楚和有益的。请问是否有什么不对。 –