Как проверить несколько вызовов методов с помощью Moq
Итак, сценарий таков: пользователь выполняет некоторые действия (например, зарабатывает значок или открывает что-то), и уведомление по электронной почте отправляется. Один для пользователя (с сообщением типа "Вы разблокировали 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));
Но я хотел быть немного более конкретным. В любом случае, чтобы сделать это?
Ответы
Ответ 1
Это можно сделать, записав, что происходит при каждом вызове 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; }
}