在单元测试中使用Moq的问题

时间:2010-12-06 20:52:01

标签: c# .net unit-testing nunit moq

我一直在探索在单元测试中使用模拟对象,并且一直在试用.NET的Moq框架。我在尝试测试从数据库返回域对象的服务层方法时遇到了一些问题。

这是我的设置:

    [SetUp]
    public void DoSetupTasks()
    {
        mockDao = new Mock<IHibernateDao>();
        _hibernateService = new HibernateService(mockDao.Object);
        mockDomainObject = new Mock<DomainBase>();
        dmBase = new DomainBase()
        {
            Id = 5
        };
    }

这是我遇到问题的单元测试。方法FindById()根据给定的ID和Type返回DomainBase对象。

    [Test]
    public void TestFindById()
    {
        mockDomainObject.Setup(dmb => dmb.Id.Equals(It.IsAny<long>())).Returns(true);
        mockDao.Setup(dao => dao.FindById(
            It.IsAny<long>(),
            It.IsAny<Type>()
        )).Returns(mockDomainObject.Object);

        _hibernateService.FindById(dmb.Id, typeof(DomainBase));
        mockDomainObject.VerifySet(dmb => dmb.Id = dmBase.Id);
    }

当我运行单元测试时,会引发以下异常:

Exception: Invalid setup on a non-virtual (overridable in VB) member: dmb => dmb.Id.Equals(It.IsAny<Int64>())

我承认,我对这个框架非常不熟悉。我一直在尝试关注它的一些教程,但我还没弄明白。

1 个答案:

答案 0 :(得分:6)

尝试更像这样的事情:

[Test]
public void TestFindById() {

    const int TEST_ID = 5;
    // Configure your mock DAO to return a real DomainBase 
    // when FindById is called.
    mockDao
        .Setup(dao => dao.FindById(TEST_ID, It.IsAny<Type>())
        .Returns(new DomainBase() { Id = TEST_ID });

    var domainObject = _hibernateService.FindById(TEST_ID , typeof(DomainBase));

    // Make sure the returned object is a DomainBase with id == TEST_ID 

    Assert.IsEqual(TEST_ID , domainObject.Id);
    Assert.IsInstanceOf<DomainBase>(domainObject);

    // and verify that your mock DAO was called with the same argument passed to 
    // your NHibernate service wrapper:
    mockDao.VerifyAll();
}

您不需要模拟域对象 - 通常最好是模拟数据层和服务,然后在测试的逻辑代码和模拟的服务层之间传递真实域对象(包含样本/测试数据)

编辑:要测试保存和删除方法,您需要执行类似的操作。注意我们如何使用Moq库的Callback()方法在调用mock方法时运行一些代码,并且在这个回调中我们断言传递给我们方法的对象是我们期望的对象:

[Test]
public void TestSaveDomainBase() {

    const int OBJECT_ID = 5;

    mockDao
      .Setup(dao => dao.Save(It.IsAny<DomainBase>()))
      .Callback((DomainBase d) => {
         // Make sure the object passed to Delete() was the correct one
         Assert.AreEqual(OBJECT_ID, d.ID);
      });

    var objectToSave = new DomainObject() { Id = OBJECT_ID };

    _hibernateService.Save(objectToDelete);

    mockDao.VerifyAll();
}


[Test]
public void TestDeleteDomainBase() {

    const int OBJECT_ID_TO_DELETE = 5;

    mockDao
      .Setup(dao => dao.Delete(It.IsAny<DomainBase>()))
      .Callback((DomainBase d) => {
         // Make sure the object passed to Delete() was the correct one
         Assert.AreEqual(OBJECT_ID_TO_DELETE, d.ID);
      });

    var objectToDelete = new DomainObject() { Id = OBJECT_ID_TO_DELETE };

    _hibernateService.Delete(objectToDelete);


    mockDao.VerifyAll();
}