如何Moq NHibernate扩展方法
本文关键字:方法 扩展 NHibernate Moq 如何 | 更新日期: 2023-09-27 18:12:03
我正在开发一个应用程序,使用NHibernate用于ORM, NUnit用于单元测试,Ninject用于我的DI。我像这样嘲弄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中模拟这样的基本查询?
Query<T>()
是一个扩展方法,这就是为什么你不能模仿它。虽然@Roger的答案是正确的,但有时进行特定的测试是有用的。你可以开始研究Query<T>()
方法做什么——要么通过阅读NHibernate代码,要么使用你自己的测试,并在issession上设置适当的方法。
警告:创建这样的设置将使您的测试非常脆弱,如果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>();
上面的第二行将抛出一个异常,并向您显示Query<T>()
扩展方法试图访问ISession
上的哪个实际属性/方法,因此您可以相应地设置它。继续这样做,最终你会有一个很好的会话设置,这样你就可以在测试中使用它了。
注意:我不熟悉NHibernate,但是当我不得不处理来自其他库的扩展方法时,我使用了上面的方法。
更新为版本5:
在新的NHibernate版本中,Query<T>
是issession接口的一部分,而不是一个扩展函数,所以它应该很容易模拟。
老回答:
我尝试了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);