Дразнить сессию NHibernate с Moq - PullRequest
       11

Дразнить сессию NHibernate с Moq

23 голосов
/ 01 декабря 2009

Я начинаю новый проект с NHibernate, ASP.NET MVC 2.0 и StructureMap и использую NUnit и Moq для тестирования. Для каждого из моих контроллеров у меня есть один публичный конструктор, в который вставляется ISession. Само приложение работает просто отлично, но с точки зрения модульного тестирования, я, по сути, должен смоделировать ISession, чтобы протестировать контроллеры.

Когда я пытаюсь смоделировать ISession с помощью MOQ, я получаю следующее сообщение об ошибке:

Поддерживается только доступ к свойствам в промежуточных вызовах

Похоже, что моя проблема заключается в ожидании списка пользователей из метода CreateQuery из фреймворка, но после поиска в Google проблемы я стал более понятным.

У меня есть два вопроса:

1) Это НЕПРАВИЛЬНЫЙ способ издеваться над внедрением зависимостей в ISession

2) Есть ли способ изменить код, чтобы он мог успешно вернуть мой список

            [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);
            }

Обратите внимание, я почти уверен, что мог бы просто создать жестко запрограммированный список пользователей (вместо того, чтобы издеваться над отдельным пользователем и добавлять его в список), но решил, что я оставлю код, как он есть сейчас.

Кроме того, действие Index этого конкретного контроллера по существу выполняет вызов CreateQuery, имитируемый выше, чтобы вернуть всех пользователей в базе данных. Это надуманный пример - не вдавайтесь в подробности.

Заранее спасибо за помощь

Редактировать: В ответ на комментарий ниже, я добавляю трассировку стека для ошибки. Кроме того, все свойства класса User являются виртуальными.

TestCase 'Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView' ошибка: System.NotSupportedException: Поддерживаются только доступы к свойствам в промежуточных вызовах на настроить. Неподдерживаемое выражение framework.CreateQuery ("от пользователя"). в Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall (MethodCallExpression м) в Moq.ExpressionVisitor.Visit (Expression эксп) в Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall (MethodCallExpression м) в Moq.ExpressionVisitor.Visit (Expression эксп) в Moq.Mock.AutoMockPropertiesVisitor.SetupMocks (Expression выражение) в Moq.Mock.GetInterceptor (LambdaExpression лямбда, издеваться над Moq.Mock. <> C__DisplayClass12 2.<Setup>b__11() at Moq.PexProtector.Invoke[T](Func 1 функция) в Moq.Mock.Setup [T1, TResult] (Mock mock, Выражение 1 expression) at Moq.Mock 1.Setup [TResult] (Expression`1 выражение) Контроллеры \ UserControllerTest.cs (29,0): в Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView ()

Ответы [ 2 ]

21 голосов
/ 02 декабря 2009

Ниже приведено решение, которое мне пришло в голову и которое, кажется, работает отлично. Опять же, я не тестирую NHibernate и не тестирую базу данных - я просто хочу протестировать контроллеры, которые зависят от NHibernate. Проблема с первоначальным решением заключается в том, что я вызывал метод, а также читал член списка сеанса в вызове установки MOQ. Я разбил эти вызовы, разбив решение на QueryMock и Session Mock (запрос на создание возвращает объект IQuery). Имитация транзакции также была необходима, поскольку она является зависимостью (в моем случае) сеанса ...

        [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);
        }
18 голосов
/ 02 декабря 2009

Вместо того, чтобы издеваться над Session, можно подумать о настройке другого Configuration для юнит-тестов. Это модульное тестирование Configuration использует быструю внутреннюю базу данных, такую ​​как SQLite или Firebird. В настройках прибора вы полностью создаете новую тестовую базу данных, запускаете сценарии для настройки таблиц и создаете набор начальных записей. В настройке для каждого теста вы открываете транзакцию, а после завершения теста - откат транзакции, чтобы восстановить базу данных до ее предыдущего состояния. В некотором смысле, вы не издеваетесь над Session, потому что это сложно, но вы издеваетесь над реальной базой данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...