3

我的应用程序正在使用 Rhino.Commons - NHRepository 和 UnitOfWork。我喜欢交易的 With.Transaction() 语法并且已经使用了一段时间。

但是我遇到了一个问题——如何模拟 UnitOfWork 进行测试?特别是这给我带来了麻烦:

With.Transaction(() => Repositories.TwinfieldSpooler.Update(spool));

我可以用 Rhino.Mocks 模拟存储库,但是我怎样才能轻松地模拟 UnitOfWork 来处理这种代码呢?

4

4 回答 4

3

With.Transaction 使用 UnitOfWork.Current 属性。UnitOfWork 是一个静态类——你不能用 RhinoMocks 模拟它。

UnitOfWork.Current 是一个公共静态属性,因此您可以将其换掉。不幸的是,setter 是内部的。

我为您看到 3 个选项:

  • 修改 Rhino.Commons 源,使 UnitOfWork.Current 设置器公开,并在您的单元测试中设置它。

  • 使用反射将 UnitOfWork.Current 设置为您的假工作单元。

  • 由于 UnitOfWork.Current 在内部使用 Local.Data 来查找当前事务,您应该可以去:

    Rhino.Commons.Local.Data[UnitOfWork.CurrentUnitOfWorkKey] = myFakeUnitOfWork;

好消息是 UnitOfWork.Current 是一个 IUnitOfWork,RhinoMocks 可以轻松伪造接口。

最后我必须说,我对 Rhino.Commons 不是很熟悉,所以 Ayende 可能已经建立了一种伪造 UnitOfWork 的正确方法。如果这对您来说非常重要,您应该在 Rhino 讨论组中提问。

于 2009-07-20T06:10:18.237 回答
2

我也有类似的需求,因为我想测试围绕持久性的逻辑,而不需要实际测试数据的持久性。UnitOfWork我发现我可以在我的测试的 SetUp 部分中轻松地使用这两行来模拟/存根:

IUnitOfWork theStubUnitOfWork = MockRepository.GenerateStub<IUnitOfWork>();
UnitOfWork.RegisterGlobalUnitOfWork(theStubUnitOfWork);
于 2009-08-12T16:28:51.990 回答
0

谢谢,但我实际上决定忽略对 Rhino 基础设施的模拟。我发现 Ayende 的这篇文章http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx关于使用每次测试都重建的 sqlite 数据库。这是一个很好的解决方案!

于 2009-08-03T18:15:49.353 回答
0

为其他人提供一点额外的信息: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);

我记得在某处看到 Ayende 的一张便条,他通常只将 With.Transaction 作为最后的手段,当他无法使用他喜欢的Castle Automatic Transaction Management时。

于 2011-08-09T01:25:53.520 回答