1

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

当我运行该应用程序时,它的工作方式与预期的一样,并且它看起来非常实用。我的业务逻辑非常孤立,我的服务层非常薄。

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

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

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

如果有帮助,我使用ASP.NET MVC 3,WCF,NHibernate和NUnit/Moq。我的单元测试调用了我的控制器动作,传递了我的服务类的实例(它们用模拟的存储库实例化)。

+1

对于什么是值得,这是一个很好的(概念)阅读这个问题:http://martinfowler.com/articles/mocksArentStubs.html –

回答

0

您正在接近这一点,因为您有一个接口代表您的存储库并在测试中传入一个伪造文件,我倾向于使用内存模拟器来存储我的存储库而不是使用mock,因为我发现存根实现倾向于使我的测试比使用模拟/验证更脆弱(因为模拟不是上面链接的存根文章)。如果您的存储库具有添加/查找/删除方法,则我的内存中实现将转发这些到成员列表,然后保存将设置一个名为SavedList的属性,我可以在我的测试中声明该属性。

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将保存改变,除非逐出被调用。

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

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