2012-02-13 65 views
2

我有下面的代碼,我需要幫助編寫一個單元測試。我正在使用Moq庫。Moq - 如何驗證方法調用哪個參數已被清除(列表)

這是交易。我有一個業務類與一個存儲庫(接口)的依賴關係,所以我可以用它來保存我的實體到數據庫。我的實體基本上是一個字符串列表。來自MyBusinessClass的方法AddAndSave獲取它接收到的值作爲參數,將它放入列表並從IRepository調用Save方法。然後,我清除我的實體列表。下面的代碼顯示了這個例子(我已經簡化了,所以我可以在這裏解釋它)。

還有一個單元測試。

using System.Collections.Generic; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using Moq; 

namespace TestesGerais 
{ 
    public class MyEntity 
    { 
     public MyEntity() 
     { 
      MyList = new List<string>(); 
     } 
     public List<string> MyList { get; set; } 
    } 

    public interface IRepository 
    { 
     void Save(MyEntity entity); 
    } 

    public class MyBusinessClass 
    { 
     public IRepository Repository { get; set; } 
     private MyEntity _entity = new MyEntity(); 
     public void AddAndSave(string info) 
     { 
      _entity.MyList.Add(info); 
      Repository.Save(_entity); 
      _entity.MyList.Clear(); // for some reason I need to clear it 
     } 
    } 

    [TestClass] 
    public class UnitTest10 
    { 
     [TestMethod] 
     public void TestMethod1() 
     { 
      var mock = new Mock<IRepository>(); 
      MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object }; 
      b.AddAndSave("xpto"); 
      mock.Verify(m => m.Save(It.Is<MyEntity>(x => x.MyList[0] == "xpto")), Times.Exactly(1)); 
     } 
    } 
} 

我的單元測試檢查,如果IRepository的保存方法,被稱爲具有列表中的一個元素,且在此元素的值「xpto」它的參數(實體)。

當我運行這個測試,它會變成紅色並顯示錯誤消息「測試方法TestesGerais.UnitTest10.TestMethod1拋出異常: System.ArgumentOutOfRangeException:索引超出範圍必須大於大小非負少。集合 參數名稱:索引「。

好的,這是由已清理的列表引起的。如果我評論「_entity.MyList.Clear();」這行,那麼一切順利。我的問題是:我如何測試這個沒有評論我的業務類中的「清除」行,並確保我的存儲庫的方法被稱爲傳遞特定的值(一個元素的值爲「xpto」)的實體?

謝謝

回答

1

我改變了我的單元測試使用Moq的回調功能。這樣,我可以設置模擬,所以當AddAndSave被調用時,它接收到的參數被保存到我的單元測試中的一個變量中,我可以在稍後聲明它。

[TestMethod] 
    public void TestMethod1() 
    { 
     var mock = new Mock<IRepository>(); 
     string result = string.Empty; 
     mock.Setup(m => m.Save(It.IsAny<MyEntity>())).Callback((MyEntity e) => { result = e.MyList[0]; }); 
     MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object }; 
     b.AddAndSave("xpto"); 
     Assert.AreEqual(result, "xpto"); 
    } 
+0

+1不錯的解決方案 – 2012-02-14 13:18:11

0

你可以分開你的方法了一下。 「AddAndSave」並不是全部。然後您可以單獨測試添加和保存位的行爲。

+0

感謝您的建議,安東尼,但方法AddAndSave是一個合同,我不想現在打破,我需要測試它的功能。但是,在這種情況下,我得到了一個讓Moq工作的訣竅,我會把它放在這裏。 – Fabio 2012-02-14 12:50:25