Moq에게 작업을 반환하도록하려면 어떻게해야합니까?


327

선언하는 인터페이스가 있습니다

Task DoSomethingAsync();

테스트에 MoqFramework를 사용하고 있습니다.

[TestMethod()]
public async Task MyAsyncTest()
{
   Mock<ISomeInterface> mock = new Mock<ISomeInterface>();
   mock.Setup(arg => arg.DoSomethingAsync()).Callback(() => { <my code here> });
   ...
}

그런 다음 테스트에서 호출하는 코드를 실행합니다 await DoSomethingAsync(). 그리고 테스트는 그 라인에서 실패합니다. 내가 뭘 잘못하고 있죠?


5
해당 라인에서 테스트 오류를 ​​말할 때 어떤 오류가 발생합니까?
AlSki

@AlSki는 NullReferenceException을 적절하게 제안합니다. 여기서
LuckyLikey

답변:


709

메소드에 콜백이 없으므로 사용할 이유가 없습니다 .CallBack(). .Returns()and Task.FromResult를 사용하여 원하는 값으로 Task를 간단히 반환 할 수 있습니다 . 예 :

MyType someValue=...;
mock.Setup(arg=>arg.DoSomethingAsync())        
    .Returns(Task.FromResult(someValue));

2014-06-22 업데이트

Moq 4.2에는이를 지원하는 두 가지 새로운 확장 방법이 있습니다.

mock.Setup(arg=>arg.DoSomethingAsync())
    .ReturnsAsync(someValue);

mock.Setup(arg=>arg.DoSomethingAsync())        
    .ThrowsAsync(new InvalidOperationException());

2016 년 5 월 5 일 업데이트

세스 꽃이에 언급 된 바와 같이 다른 대답 , ReturnsAsync를 돌려주는 메소드에만 사용할 수 있습니다 Task<T>. 작업 만 반환하는 메서드의 경우

.Returns(Task.FromResult(default(object)))

사용할 수 있습니다.

이 답변 에서 볼 수 있듯이 .NET 4.6에서는 다음과 같이 단순화되었습니다 .Returns(Task.CompletedTask);.

mock.Setup(arg=>arg.DoSomethingAsync())        
    .Returns(Task.CompletedTask);

16
. 반품 (Task.CompletedTask); 그게 내 대답이었습니다
Todd Vance

8
Moq 프레임 워크가 업데이트되었으므로이 답변을 최신 상태로 유지해 주셔서 감사합니다!
Jacob Stamm

.Returns(Task.FromResult(default(object))반환 유형이 무효 인 경우 잘 작동합니다. .Returns(Task.FromResult(null as MyType))예상 반환 유형이 null 인 경우 잘 작동합니다.
Jeremy Ray Brown

1
.NET 4.6에서는 @JeremyRayBrown default(object)이 더 이상 필요하지 않습니다. null as MyType와 동일한 default(MyType)길이만큼 MyType참조 형식이다.
Panagiotis Kanavos

40

비슷한 문제

대략 다음과 같은 인터페이스가 있습니다.

Task DoSomething(int arg);

조짐

테스트중인 서비스에서 awaited에 전화를 걸 때 유닛 테스트에 실패했습니다 DoSomething.

고치다

허용 대답과는 달리, 당신은 전화를 할 수없는 .ReturnsAsync()당신의 Setup()방법은 제네릭이 아닌를 반환하기 때문에이 시나리오에서이 방법 Task보다는 Task<T>.

그러나 .Returns(Task.FromResult(default(object)))설정에서 계속 사용할 수있어 테스트를 통과 할 수 있습니다.


1
제네릭이 아닌 작업 (.net 4.6이 아닌)을 반환 해야하는 경우 Task.Delay (1)을 반환하는 쉬운 방법으로 작업을 반환하는 것이 좋습니다. 시간 인수를 늘려서 작업을 흉내낼 수도 있습니다.
stevethethread

26

.Returns(Task.FromResult(0));콜백 후에 만 추가 하면됩니다.

예:

mock.Setup(arg => arg.DoSomethingAsync())
    .Callback(() => { <my code here> })
    .Returns(Task.FromResult(0));

4

이제 Talentsoft.Moq.SetupAsync 패키지 https://github.com/TalentSoft/Moq.SetupAsync 를 사용할 수도 있습니다.

https://github.com/moq/moq4/issues/384 여기에서 발견 된 답변과 Moq에 제안되었지만 여전히 구현되지 않은 아이디어를 기반으로 비동기 메소드 설정을 크게 단순화합니다.

SetupAsync 확장으로 수행 된 이전 응답에서 몇 가지 예를 발견했습니다.

mock.SetupAsync(arg=>arg.DoSomethingAsync());
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Callback(() => { <my code here> });
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Throws(new InvalidOperationException());
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.