如何使用Moq NHibernate扩展方法?

时间:2013-05-03 12:03:53

标签: c# linq nhibernate ninject moq

我正在使用NHibernate为ORM开发应用程序,使用NUnit进行单元测试,为我的DI开发Ninject。我这样嘲笑ISession:

var session = new Mock<ISession>();

使用常规的非模拟会话对象,我可以使用LINQ扩展方法查询它们:

var result = Session.Query<MyEntity>();

但是当我尝试使用以下代码模拟它时......

session.Setup(s => s.Query<MyEntity>());

...我得到一个运行时“不支持”例外:

Expression references a method that does not belong to the mocked object: s => s.Query<MyEntity>()

如何在Moq / NHibernate中模拟这样的基本查询?

2 个答案:

答案 0 :(得分:3)

Query<T>()是一种扩展方法,这就是为什么你不能嘲笑它。 虽然@Roger的答案是可行的,但有时候进行特定测试会很有用。您可以通过阅读NHibernate代码或使用自己的测试开始调查Query<T>()方法的作用,并在ISession上设置适当的方法。

警告:创建此类设置会使您的测试非常脆弱,如果NHibernate的内部实现发生变化,它将会中断。

无论如何,您可以通过以下方式开始调查:

var mockSession = new Mock<ISession>(MockBehavior.Strict); //this will make the mock to throw on each invocation which is not setup
var entities = mockSession.Object.Query<MyEntity>();

上面的第二行将抛出异常并显示ISession Query<T>()扩展方法尝试访问的{{1}}上的实际属性/方法,因此您可以相应地设置它。继续这样,最终你会有一个很好的会话设置,所以你可以在测试中使用它。

注意:我不熟悉NHibernate,但是当我不得不处理来自其他库的扩展方法时,我已经使用了上述方法。

答案 1 :(得分:1)

我尝试了Sunny的建议并且做到了这一点,但是因为IQuery被投射到内部的NHibernate.Impl.ExpressionQueryImpl并且我认为不能延长而被卡住了。只需发布此信息即可将其他失去的灵魂保存几个小时。

var sessionImplMock = new Mock<NHibernate.Engine.ISessionImplementor>(MockBehavior.Strict);
var factoryMock = new Mock<NHibernate.Engine.ISessionFactoryImplementor>(MockBehavior.Strict);
var queryMock = new Mock<IQuery>(MockBehavior.Strict);//ExpressionQueryImpl

sessionImplMock.Setup(x => x.Factory).Returns(factoryMock.Object);
sessionImplMock.Setup(x => x.CreateQuery(It.IsAny<IQueryExpression>())).Returns(queryMock.Object);
sessionMock.Setup(x => x.GetSessionImplementation()).Returns(sessionImplMock.Object);