답변:
이기기 어렵다 https://github.com/Moq/moq4/wiki/Quickstart
그것이 충분히 명확하지 않다면 나는 그것을 문서 버그라고 부를 것입니다.
편집 : 귀하의 설명에 대한 응답으로 ...
Setup
수행하는 각 모의 방법에 대해 다음과 같은 것을 나타냅니다.
.Callback
메커니즘은 "나는 지금 그것을 설명 할 수는 없지만이 모양의 호출이 발생했을 때, 내가 다시 전화해서 내가 일을해야 일을 할 것이다"라고. 동일한 유창한 콜 체인의 일부로 .Returns
" 를 통해 반환 할 결과 (있는 경우)를 제어 할 수 있습니다 . QS 예제에서 반환되는 값이 매번 증가하도록 만드는 것이 예입니다.
일반적으로 이와 같은 메커니즘은 자주 필요하지 않으며 (xUnit 테스트 패턴에는 테스트에서 ilk 조건부 논리의 반 패턴에 대한 용어가 있습니다) 필요한 것을 설정하는 더 간단하거나 내장 된 방법이 있다면 선호도에 사용됩니다.
Justin Etheredge의 Moq 시리즈 4 부 중 3 부에서 이를 다룹니다. 여기에 콜백의 또 다른 예가 있습니다.
Callback
는 반환 값과 관련이 없습니다 (코드를 통해 링크하지 않는 한). 기본적으로 콜백이 각 호출 이전 또는 이후에 호출되는지 확인합니다 ( Returns
각각 이전 또는 이후에 연결했는지 여부에 따라 다름 ), 단순하고 간단합니다.
다음은 삽입을 처리하는 데이터 서비스에 전송 된 엔터티를 테스트하기 위해 콜백을 사용하는 예입니다.
var mock = new Mock<IDataService>();
DataEntity insertedEntity = null;
mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1)
.Callback((DataEntity de) => insertedEntity = de);
대체 일반 메서드 구문 :
mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1)
.Callback<DataEntity>(de => insertedEntity = de);
그런 다음 다음과 같은 것을 테스트 할 수 있습니다.
Assert.AreEqual("test", insertedEntity.Description, "Wrong Description");
It.Is<T>
로 처리하는 Mock.Verify
대신 in 을 사용하는 것이 더 깨끗할 수 있습니다. 하지만 +1은 예에서 가장 잘 작동하는 사람들이 많기 때문입니다.
Callback
Moq 에는 두 가지 유형이 있습니다 . 호출이 반환되기 전에 하나가 발생합니다. 다른 하나는 호출이 반환 된 후에 발생합니다.
var message = "";
mock.Setup(foo => foo.Execute(arg1: "ping", arg2: "pong"))
.Callback((x, y) =>
{
message = "Rally on!";
Console.WriteLine($"args before returns {x} {y}");
})
.Returns(message) // Rally on!
.Callback((x, y) =>
{
message = "Rally over!";
Console.WriteLine("arg after returns {x} {y}");
});
두 콜백 모두에서 다음을 수행 할 수 있습니다.
Callback
모의 메소드 중 하나를 호출 할 때 원하는 사용자 정의 코드를 실행하는 수단 일뿐입니다. 다음은 간단한 예입니다.
public interface IFoo
{
int Bar(bool b);
}
var mock = new Mock<IFoo>();
mock.Setup(mc => mc.Bar(It.IsAny<bool>()))
.Callback<bool>(b => Console.WriteLine("Bar called with: " + b))
.Returns(42);
var ret = mock.Object.Bar(true);
Console.WriteLine("Result: " + ret);
// output:
// Bar called with: True
// Result: 42
최근에 흥미로운 사용 사례를 접했습니다. 모의에 대한 일부 호출을 예상하지만 동시에 발생한다고 가정합니다. 따라서 호출되는 순서를 알 수있는 방법이 없지만 예상 한 호출이 (순서에 관계없이) 발생했는지 알고 싶습니다. 다음과 같이 할 수 있습니다.
var cq = new ConcurrentQueue<bool>();
mock.Setup(f => f.Bar(It.IsAny<bool>())).Callback<bool>(cq.Enqueue);
Parallel.Invoke(() => mock.Object.Bar(true), () => mock.Object.Bar(false));
Console.WriteLine("Invocations: " + String.Join(", ", cq));
// output:
// Invocations: True, False
BTW는 오해의 소지가있는 "이전 Returns
"과 "이후 Returns
"구분으로 혼동하지 않습니다 . 사용자 지정 코드가 Returns
평가 된 후 또는 이전에 실행되는지 여부에 대한 기술적 인 차이 일뿐 입니다. 호출자의 눈에는 값이 반환되기 전에 둘 다 실행됩니다. 실제로 메서드가 void
-returning이면 호출조차 할 수 없지만 여전히 Returns
동일하게 작동합니다. 자세한 내용은 https://stackoverflow.com/a/28727099/67824를 참조 하십시오 .