Как вы издеваетесь над UnitOfWork из Rhino.Commons?
Мое приложение использует Rhino.Commons - NHRepository и UnitOfWork. Мне нравится синтаксис With.Transaction() для транзакций, и я использую его в течение некоторого времени.
Но я столкнулся с проблемой - как мне издеваться над UnitOfWork для тестирования? Особенно это доставляет мне неприятности:
With.Transaction(() => Repositories.TwinfieldSpooler.Update(spool));
Я могу смоделировать репозитории с помощью Rhino.Mocks, но как я могу легко смоделировать UnitOfWork для такого рода кода?
4 ответа
Спасибо, но я на самом деле решил игнорировать насмешки над инфраструктурой Rhino. Я нашел это сообщение Ayende http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx об использовании базы данных sqlite, перестраиваемой с каждым тестом. Это было отличное решение!
У меня была аналогичная потребность, потому что я хотел проверить логику постоянства без фактического тестирования постоянства данных. Я обнаружил, что могу издеваться UnitOfWork
легко используя эти 2 строки в части моих тестов SetUp:
IUnitOfWork theStubUnitOfWork = MockRepository.GenerateStub<IUnitOfWork>();
UnitOfWork.RegisterGlobalUnitOfWork(theStubUnitOfWork);
With.Transaction использует свойство UnitOfWork.Current. UnitOfWork является статическим классом - вы не можете высмеивать его с помощью RhinoMocks.
UnitOfWork.Current является публичным статическим свойством, поэтому вы можете поменять его. К сожалению, сеттер является внутренним.
Я вижу 3 варианта для вас:
Измените исходный код Rhino.Commons, чтобы сделать установщик UnitOfWork.Current общедоступным, и установите его в своем модульном тесте.
Используйте отражение, чтобы установить UnitOfWork.Current для вашей поддельной единицы работы.
Поскольку UnitOfWork.Current внутренне использует Local.Data для поиска текущей транзакции, вы должны иметь возможность перейти:
Rhino.Commons.Local.Data [UnitOfWork.CurrentUnitOfWorkKey] = myFakeUnitOfWork;
Хорошей новостью является то, что UnitOfWork.Current является IUnitOfWork, и RhinoMocks может легко подделывать интерфейсы.
Я должен закончить словами: я не очень знаком с Rhino.Commons, поэтому Айенде могла бы придумать правильный способ подделать UnitOfWork. Если это очень важно для вас, вы должны спросить в дискуссионных группах Rhino.
Просто дополнительная информация для других: Ogre Psalm33 упомянул, как заглушить UnitOfWork, но если вы также хотите, чтобы With.Transaction работал, вы можете дополнительно заглушить RhinoTransaction:
IUnitOfWork stubUnitOfWork = MockRepository.GenerateStub<IUnitOfWork>();
RhinoTransaction stubTx = MockRepository.GenerateStub<RhinoTransaction>();
stubUnitOfWork.Expect(x => x.BeginTransaction(System.Data.IsolationLevel.Unspecified)).IgnoreArguments().Return(stubTx);
UnitOfWork.RegisterGlobalUnitOfWork(stubUnitOfWork);
Я помню, как видел где-то заметку от Айенде, что он обычно использовал With.Transaction только в качестве крайней меры, когда он не мог использовать свой предпочтительный Castle Automatic Transaction Management.