2010-12-06 60 views
2

我一直在探索在單元測試中使用模擬對象,並且一直在嘗試用於.NET的Moq框架。我在嘗試測試從數據庫返回域對象的服務層方法時遇到了一些問題。在單元測試中使用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和類型返回一個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>())

我得承認,我與框架相當陌生。我一直在試着去關注一些教程,但是我一直無法弄清楚它。

回答

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(); 
} 

你不應該需要模擬你的域對象 - 你一般最好嘲笑你的數據層和服務,然後通過真正的域對象(含樣本/測試數據)在您的邏輯代碼與您的模擬服務層之間。

編輯:要測試保存和刪除方法,你會想要做這樣的事情。請注意,在調用mock方法時,我們如何使用Moq庫的Callback()方法運行一些代碼,並且在此回調中,我們聲明傳遞給我們方法的對象是我們期望的對象:

[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(); 
} 
+0

謝謝!我會給出一個答案,並在明天回來報告,但僅僅基於查看您的代碼,它現在變得更加合理。 – 2010-12-06 22:35:38