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());
}
그런데 Verify 호출에서 식을 어떻게 추출 할 수 있습니까?
답변
검증 로직이 사소한 것이 아니라면 (예에서 보듯이) 큰 람다 방법을 작성하는 것이 지저분합니다. 모든 테스트 문을 별도의 방법으로 넣을 수는 있지만 테스트 코드 읽기 흐름을 방해하기 때문에 이것을 좋아하지 않습니다.
또 다른 옵션은 Setup 호출에서 콜백을 사용하여 모의 메소드에 전달 된 값을 저장 한 다음 표준 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의 버그에 유의하십시오. 그들은 지금까지 그것을 고쳤을 것입니다. 그러나 당신이 그 메시지를 보게되면 메소드가 실제로 호출되었는지 확인하는 것을 고려할 수 있습니다.
편집 : 다음은 목록의 각 객체에 대해 함수를 호출하는지 확인하려는 시나리오에서 여러 번 확인을 호출하는 예입니다 (예 :).
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);
}
따라서 해당 itemId에 대해 GetStuff가 호출 될 때마다 해당 항목에 특정한 항목을 반환합니다. 또는 itemId를 입력으로 받아서 물건을 반환하는 함수를 사용할 수 있습니다.
this.mockRepository
.Setup(mr => mr.GetStuff(It.IsAny<int>()))
.Returns((int id) => SomeFunctionThatReturnsStuff(id));
필자가 언젠가 블로그에서 보았던 다른 방법 (Phil Haack?)은 일종의 dequeue 객체에서 돌아 오는 설정을 가지고 있습니다. 함수가 호출 될 때마다 대기열에서 항목을 가져옵니다.
답변
더 간단한 방법은 다음과 같습니다.
ObjectA.Verify(
a => a.Execute(
It.Is<Params>(p => p.Id == 7)
)
);
답변
나는 Moq가 평등을 점검한다는 사실의 문제를 믿는다. 그리고 XmlElement는 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
}