1

我正在开展一个新项目,我正在积极尝试尊重持久性无知。例如,在我的服务层中,我从 ORM 中检索一个实体,然后调用在实体上定义的例程,该例程可能会或可能不会对实体进行更改。然后我依靠我的 ORM 来检测实体是否被修改并进行必要的插入/更新/删除。

当我运行该应用程序时,它按预期工作,并且看到它在运行中真的很整洁。我的业务逻辑非常孤立,我的服务层非常薄。

当然,现在我正在添加单元测试,我注意到我不能再编写单元测试来验证某些属性是否被修改。在我之前的解决方案中,我确定是否对处于预期状态的对象进行了存储库调用。

mockRepository.Verify(mr => 
  mr.SaveOrUpdate(It.Is<MyEntity>(x => 
    x.Id == 123 && x.MyProp == "newvalue")), Times.Once());

我是否正确地接近持久性无知?当我没有显式调用存储库的保存方法时,是否有更好的方法来对我的实体的操作后状态进行单元测试?

如果有帮助,我正在使用 ASP.NET MVC 3、WCF、NHibernate 和 NUnit/Moq。我的单元测试通过我的服务类的实例(使用模拟存储库实例化)调用我的控制器操作。

4

2 回答 2

0

奇怪的是,我偶然发现了一个解决方案,它真的很简单。

[Test]
public void Verify_Widget_Description_Is_Updated()
{
  // arrange
  var widget = new Widget { };
  mockWidgetRepo.Setup(mr => mr.GetWidget()).returns(widget);

  var viewModel = new WidgetVM { };
  viewModel.Description = "New Desc";  

  // act
  var result = (ViewResult)controller.UpdateWidget(viewModel);

  // assert
  Assert.AreEqual("New Desc", widget.Description);
}

这并不完美,但我可以假设如果 widget.Description 与我分配给我的视图模型的值匹配,那么 ORM 将保存该更改,除非调用 evict。

更新: 刚刚想出了另一个替代解决方案。我在我的基本存储库中创建了一个 ObjectStateAssertionForTests(Object obj) 函数,它什么都不做。我可以在我的代码中调用这个函数,然后在我的单元测试中检查它。

mockRepository.Verify(mr => 
  mr.ObjectStateAssertionForTests(It.Is<MyEntity>(x => 
    x.Id == 123 && x.MyProp == "newvalue")), Times.Once());
于 2011-10-25T18:19:27.363 回答
0

您正在正确地处理这个问题,因为您有一个代表您的存储库的接口并在您的测试中传入一个假的,我更喜欢为我的存储库使用内存模拟器而不是使用模拟,因为我发现存根实现倾向于使我的测试比使用模拟/验证更脆弱(根据模拟不是上面链接的存根文章)。如果您的存储库具有 Add/Find/Delete 方法,我的内存实现会将这些方法转发到成员列表,然后 save 将设置一个名为 SavedList 的属性,我可以在测试中对其进行断言。

于 2011-07-06T03:06:13.180 回答