嘲弄一个NHibernate的ISession带起订量NHibernate、ISession、带起订量

2023-09-02 10:55:30 作者:超音速奔跑的蝸牛

我开始与NHibernate,ASP.NET MVC 2.0和StructureMap一个新的项目,并使用NUnit和起订量进行检测。对于我的每个控制器我有一个单一的公共构造成一个ISession被注入。该应用程序本身工​​作得很好,但在单元测试方面,我基本上都嘲笑一个ISession为了测试控制器。

当我试图嘲弄的ISession与MOQ我收到以下错误消息:

  

只有属性访问支持   中间调用

看来,我的问题是希望从框架的createQuery方法的用户列表中,但使用Google发出后,我现在更清楚。

我有两个问题:

1),这是错误的方式来嘲笑依赖注入一个ISession的

2)有没有办法来修改code,以便它可以成功返回我的列表

  [测试]
            公共无效DummyTest()
            {

                VAR模拟=新的模拟< ISession的>();
                VAR LOC =新的模拟<使用者>();
                loc.SetupGet(X => x.ID).Returns(2);
                loc.SetupGet(X => x.FirstName).Returns(约翰);
                loc.SetupGet(X => x.LastName).Returns(彼得森);

                VAR LST =新的List<使用者> {loc.Object};
                mock.Setup(框架=> framework.CreateQuery(从用户)名单,其中;。使用者>())返回(LST)。

                无功控制=新UsersController中(mock.Object);
                VAR的结果= controller.Index()作为的ViewResult;
               Assert.IsNotNull(result.ViewData);
            }
 

请注意,我是pretty的肯定,我可以只创建用户的硬codeD列表(而不是嘲讽单个用户并将其添加到列表中),但想我会离开的code,因为我有现在。

此外,这个特殊的控制器的索引动作基本上执行的createQuery调用模仿上面返回所有数据库中的用户。这是一个人为的例子 - 不读任何东西到细节

在此先感谢您的帮助

编辑:在回答下面的评论,我加入的堆栈跟踪的错误。此外,在用户类的所有属性都是虚拟的。

  

测试用例   Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView   失败:System.NotSupportedException:   只有属性访问支持   在一个中间调用   建立。不支持的EX pression   framework.CreateQuery(从用户)。     在   Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall(MethodCallEx pression   垫   Moq.Ex pressionVisitor.Visit(出pression   EXP)在   Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall(MethodCallEx pression   垫   Moq.Ex pressionVisitor.Visit(出pression   EXP)在   Moq.Mock.AutoMockPropertiesVisitor.SetupMocks(前pression   EX pression)在   Moq.Mock.GetInterceptor(LambdaEx pression   拉姆达,模拟模拟)在   Moq.Mock<> c__DisplayClass12 2<设置> b__11()     在Moq.PexProtector.Invoke [T](Func键 1   功能)在   Moq.Mock.Setup1 EX pression)在   Moq.Mock1.Setup%5BTResult%5D%28Ex pression`1   EX pression> T1,TResult     控制器 UserControllerTest.cs(29,0):   在   Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView()

解决方案

下面是解决方案,我想出了这似乎很好地工作。同样,我不测试NHibernate和我没有测试数据库 - 我只是想测试依赖于NHibernate的控制器。与最初的解决方案,这个问题似乎是事实,我是调用一个方法,以及在读的起订量建立呼叫会话的列表成员。我分手了这些呼叫通过打破解成QueryMock和会话模拟(创建查询返回IQUERY对象)。事务模拟也是必要的,因为它是一个依赖(在我的情况)的会议......

  [测试]
        公共无效DummyTest()
        {
            VAR用户列表=新的List<使用者>(){新用户(){n = 2,名字=约翰,名字=彼得森}};
            VAR sessionMock =新的模拟< ISession的>();
            VAR queryMock =新的模拟< IQUERY>();
            VAR transactionMock =新的模拟< ITransaction>();

            sessionMock.SetupGet(X => x.Transaction).Returns(transactionMock.Object);
            sessionMock.Setup(会话=> session.CreateQuery(从用户))将返回(queryMock.Object)。
            queryMock.Setup(X => x.List<使用者>())返回(用户列表)。

            无功控制=新UsersController中(sessionMock.Object);
            VAR的结果= controller.Index()作为的ViewResult;
            Assert.IsNotNull(result.ViewData);
        }
 
这些实用手机订票 小技巧 您知道吗

I am starting a new project with NHibernate, ASP.NET MVC 2.0 and StructureMap and using NUnit and Moq for testing. For each of my controllers I have a single public constructor into which an ISession is being injected. The application itself works just fine, but in terms of unit testing I essentially have to mock an ISession in order to test the controllers.

When I attempt to Mock the ISession with MOQ i get the following error message:

Only property accesses are supported in intermediate invocations

It appears that my problem is expecting List of users from the framework CreateQuery method but after googling the issue I am now clearer.

I have two questions:

1) Is this the WRONG way to mock dependency injection of an ISession

2) Is there a way to modify the code so that it can successfully return my list

            [Test]
            public void DummyTest()
            {

                var mock = new Mock<ISession>();
                var loc = new Mock<User>();
                loc.SetupGet(x => x.ID).Returns(2);
                loc.SetupGet(x => x.FirstName).Returns("John");
                loc.SetupGet(x => x.LastName).Returns("Peterson");

                var lst = new List<User> {loc.Object};
                mock.Setup(framework => framework.CreateQuery("from User").List<User>()).Returns(lst);

                var controller = new UsersController(mock.Object);
                var result = controller.Index() as ViewResult;
               Assert.IsNotNull(result.ViewData);
            }

Please note, I am pretty sure I could just create a hard-coded list of users (rather than mocking an individual User and adding it to a list) but figured I'd leave the code as I have it right now.

Also, the Index action of this particular controller essentially executes the CreateQuery call mimicked above to return all users in the database. This is a contrived example - don't read anything into the details.

Thanks in advance for your help

Edit: In reply to the below comment, I am adding the stacktrace for the error. Also, all properties on the User class are virtual.

TestCase 'Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView' failed: System.NotSupportedException : Only property accesses are supported in intermediate invocations on a setup. Unsupported expression framework.CreateQuery("from User"). at Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall(MethodCallExpression m) at Moq.ExpressionVisitor.Visit(Expression exp) at Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall(MethodCallExpression m) at Moq.ExpressionVisitor.Visit(Expression exp) at Moq.Mock.AutoMockPropertiesVisitor.SetupMocks(Expression expression) at Moq.Mock.GetInterceptor(LambdaExpression lambda, Mock mock) at Moq.Mock.<>c__DisplayClass122.<Setup>b__11() at Moq.PexProtector.Invoke[T](Func1 function) at Moq.Mock.Setup1 expression) at Moq.Mock1.Setup%5BTResult%5D%28Expression`1 expression">T1,TResult ControllersUserControllerTest.cs(29,0): at Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView()

解决方案

Below is the solution I came up with which seems to work perfectly. Again, I am not testing NHibernate and I am not testing the database - I simply want to test the controllers which depend on NHibernate. The issue with the initial solution appears to be the fact that I was calling a Method as well as reading the List member of the session in the MOQ setup call. I broke up these calls by breaking the solution into a QueryMock and a Session Mock (create query returns an IQuery object). A transaction mock was also necessary as it is a dependency (in my case) of the session...

        [Test]
        public void DummyTest()
        {
            var userList = new List<User>() { new User() { ID = 2, FirstName = "John", LastName = "Peterson" } };
            var sessionMock = new Mock<ISession>();
            var queryMock = new Mock<IQuery>();
            var transactionMock = new Mock<ITransaction>();

            sessionMock.SetupGet(x => x.Transaction).Returns(transactionMock.Object);
            sessionMock.Setup(session => session.CreateQuery("from User")).Returns(queryMock.Object);
            queryMock.Setup(x => x.List<User>()).Returns(userList);

            var controller = new UsersController(sessionMock.Object);
            var result = controller.Index() as ViewResult;
            Assert.IsNotNull(result.ViewData);
        }