2011-06-08 38 views
14

的電話,以情景是這樣的:用戶執行某些操作(如賺取徽章或解鎖的東西)和電子郵件通知被髮送出去。一個給用戶(帶有「你已經解鎖了XYZ ......」等信息),然後向他們的每個朋友發送不同的信息,比如(「你是朋友已經解鎖了XYZ ...」)。如何驗證多種方法與起訂量

public interface INotify 
{ 
    void Notify(User user, User friend); 
} 

public class NotificationService 
{ 
    private IEnumerable<INotify> _notifiers; 

    public NotificationService(IEnumerable<INotify> notifiers) 
    { 
     _notifiers = notifiers; 
    } 

    public SendNotifications() 
    { 
     User user = GetUser(); 
     IEnumerable<User> friends = GetFriends(); 

     foreach(var notifier in _notifiers) 
     { 
      //Send notification to user 
      notifier.Notify(user, null); 

      //send notification to users friends 
      foreach(var friend in friends) 
       notifier.Notify(user, friend); 
     } 
    } 
} 

我試圖用moq來測試每個通知器被稱爲2x。一旦傳遞null作爲第二個參數,第二次傳入一個值給兩個參數。

[Test] 
public void MakeSureEveryoneIsNotified() 
{ 
    var notifierMock = new Mock<INotifier>(); 

    var svc = new NotificationService(new List<INotifier>{ notifierMock.Object });  
    svc.SendNotifications(); 

    notifierMock.Verify(x => x.Notify(It.Is<User>(user => user.UserId == 1), null), Times.Once()); 
    notifierMock.Verify(x => x.Notify(It.Is<User>(user => user.UserId == 1), It.Is<User>(user => user.UserId == 2)), Times.Once()); 
} 

問題是第二個驗證調用爲第二個參數拋出ArgumentNullException。有沒有說「檢查第一個電話有這些參數,然後第二個電話有其他參數」。我知道我可以簡單地通過調用得到它周圍:

notifierMock.Verify(x => x.Notify(It.IsAny<User>(), It.IsAny<User>()), Times.Exactly(2)); 

但我想成爲一個更具體一點。無論如何要做到這一點?

+0

您是否嘗試過在.Verify語句之外創建一個用戶並將該用戶用作參數? – 2011-06-08 03:25:54

+0

我刪除的依賴上的getUser()方法中,創建一個用戶提供,嘲笑它,然後存根提供者的相關部分。 – 2011-06-08 03:30:12

+0

GetUser方法實際上來自注入到類中的外部依賴項,但爲了簡潔起見我省略了它。第一個選項應該可以工作 – Micah 2011-06-08 03:42:46

回答

18

您可以通過記錄在每次調用Notify發生了什麼做到這一點。然後你可以比較記錄與預期的結果:

[TestMethod] 
public void TestMoqInvocations() 
{ 
    var notifierMock = new Mock<INotifier>(); 

    var svc = new NotificationService(new List<INotifier>{ notifierMock.Object });  
    svc.SendNotifications(); 

    var invocations = new List<NotifyParams>(); 

    notifierMock 
     .Setup(f => f.Notify(It.IsAny<User>(), It.IsAny<User>())) 
     .Callback<string, string>((user, friend) => invocations.Add(new NotifyParams{user = user, friend = friend})); 

    Assert.AreEqual(1, invocations[0].user.UserId); 
    Assert.IsNull(invocations[0].friend); 
    Assert.AreEqual(1, invocations[1].user.UserId); 
    Assert.AreEqual(2, invocations[1].user.UserId); 
} 

public struct NotifyParams { 
    public User user {get;set;} 
    public User friend { get; set; } 
}