Проверка конкретного параметра с помощью Moq
public void SubmitMessagesToQueue_OneMessage_SubmitSuccessfully()
{
var messageServiceClientMock = new Mock<IMessageServiceClient>();
var queueableMessage = CreateSingleQueueableMessage();
var message = queueableMessage[0];
var xml = QueueableMessageAsXml(queueableMessage);
messageServiceClientMock.Setup(proxy => proxy.SubmitMessage(xml)).Verifiable();
//messageServiceClientMock.Setup(proxy => proxy.SubmitMessage(It.IsAny<XmlElement>())).Verifiable();
var serviceProxyFactoryStub = new Mock<IMessageServiceClientFactory>();
serviceProxyFactoryStub.Setup(proxyFactory => proxyFactory.CreateProxy()).Returns(essageServiceClientMock.Object);
var loggerStub = new Mock<ILogger>();
var client = new MessageClient(serviceProxyFactoryStub.Object, loggerStub.Object);
client.SubmitMessagesToQueue(new List<IMessageRequestDTO> {message});
//messageServiceClientMock.Verify(proxy => proxy.SubmitMessage(xml), Times.Once());
messageServiceClientMock.Verify();
}
Я начинаю использовать Moq и немного борюсь.
Я пытаюсь проверить, что messageServiceClient получает правильный параметр, который является XmlElement, но я не могу найти никакого способа заставить его работать. Он работает только тогда, когда я не проверяю определенное значение.
Есть идеи?
Частичный ответ:
Я нашел способ проверить, что xml, отправленный на прокси, является правильным, но я все еще не думаю, что это правильный способ сделать это.
public void SubmitMessagesToQueue_OneMessage_SubmitSuccessfully()
{
var messageServiceClientMock = new Mock<IMessageServiceClient>();
messageServiceClientMock.Setup(proxy => proxy.SubmitMessage(It.IsAny<XmlElement>())).Verifiable();
var serviceProxyFactoryStub = new Mock<IMessageServiceClientFactory>();
serviceProxyFactoryStub.Setup(proxyFactory => proxyFactory.CreateProxy()).Returns(messageServiceClientMock.Object);
var loggerStub = new Mock<ILogger>();
var client = new MessageClient(serviceProxyFactoryStub.Object, loggerStub.Object);
var message = CreateMessage();
client.SubmitMessagesToQueue(new List<IMessageRequestDTO> {message});
messageServiceClientMock.Verify(proxy => proxy.SubmitMessage(It.Is<XmlElement>(xmlElement => XMLDeserializer<QueueableMessage>.Deserialize(xmlElement).Messages.Contains(message))), Times.Once());
}
Кстати, как я могу извлечь выражение от звонка с проверкой?
5 ответов:
Если логика верификации нетривиальна, то написать большой лямбда-метод (как показывает ваш пример) будет непросто. Вы можете поместить все тестовые операторы в отдельный метод, но мне не нравится это делать, потому что это нарушает поток чтения тестового кода.
Другой вариант - использовать обратный вызов для вызова Setup, чтобы сохранить значение, переданное в метод mocked, а затем записать стандартные методыAssertдля его проверки. Например:// Arrange MyObject saveObject; mock.Setup(c => c.Method(It.IsAny<int>(), It.IsAny<MyObject>())) .Callback<int, MyObject>((i, obj) => saveObject = obj) .Returns("xyzzy"); // Act // ... // Assert // Verify Method was called once only mock.Verify(c => c.Method(It.IsAny<int>(), It.IsAny<MyObject>()), Times.Once()); // Assert about saveObject Assert.That(saveObject.TheProperty, Is.EqualTo(2));
Я проверял звонки таким же образом - я считаю, что это правильный способ сделать это.
mockSomething.Verify(ms => ms.Method( It.IsAny<int>(), It.Is<MyObject>(mo => mo.Id == 5 && mo.description == "test") ), Times.Once());Если ваше лямбда-выражение становится громоздким, вы можете создать функцию, которая принимает
MyObjectв качестве входных и выходных данныхtrue/false...mockSomething.Verify(ms => ms.Method( It.IsAny<int>(), It.Is<MyObject>(mo => MyObjectFunc(mo)) ), Times.Once()); private bool MyObjectFunc(MyObject myObject) { return myObject.Id == 5 && myObject.description == "test"; }Кроме того, обратите внимание на ошибку с Mock, где сообщение об ошибке указывает, что метод вызывался несколько раз, когда он не вызывался вообще. Возможно, они уже починили его - но если вы видите это сообщение, вы можете проверить, что метод был фактически вызван.
EDIT: вот пример многократного вызова функции verify для тех сценариев, где требуется проверить, что вы вызываете функцию для каждого объекта в списке (например).
foreach (var item in myList) mockRepository.Verify(mr => mr.Update( It.Is<MyObject>(i => i.Id == item.Id && i.LastUpdated == item.LastUpdated), Times.Once());Тот же подход для установки...
foreach (var item in myList) { var stuff = ... // some result specific to the item this.mockRepository .Setup(mr => mr.GetStuff(item.itemId)) .Returns(stuff); }Поэтому каждый раз, когда GetStuff вызывается для этого itemId, он возвращает материал, специфичный для этого элемента. В качестве альтернативы можно использовать функцию, которая принимает itemId в качестве входных данных и возвращает данные.
this.mockRepository .Setup(mr => mr.GetStuff(It.IsAny<int>())) .Returns((int id) => SomeFunctionThatReturnsStuff(id));Еще один метод, который я видел на блог некоторое время назад (Фил Хаак, возможно?) имел setup, возвращающийся из какого - то объекта dequeue-каждый раз, когда функция вызывалась, она вытягивала элемент из очереди.
Я считаю, что проблема в том, что Moq будет проверять на равенство. И, поскольку XmlElement не переопределяет Equals, его реализация будет проверять равенство ссылок.
Нельзя ли использовать пользовательский объект, чтобы переопределить equals?
Также имел один из них, но параметром действия был интерфейс без каких-либо публичных свойств. В конечном итоге с помощью It.Is () с отдельным методом и в рамках этого метода пришлось сделать некоторое глумление над интерфейсом
public interface IQuery { IQuery SetSomeFields(string info); } void DoSomeQuerying(Action<IQuery> queryThing); mockedObject.Setup(m => m.DoSomeQuerying(It.Is<Action<IQuery>>(q => MyCheckingMethod(q))); private bool MyCheckingMethod(Action<IQuery> queryAction) { var mockQuery = new Mock<IQuery>(); mockQuery.Setup(m => m.SetSomeFields(It.Is<string>(s => s.MeetsSomeCondition()) queryAction.Invoke(mockQuery.Object); mockQuery.Verify(m => m.SetSomeFields(It.Is<string>(s => s.MeetsSomeCondition(), Times.Once) return true }
Comments