xUnit和Moq不支持async – 等待关键字

我试图发现如何将async和await关键字应用于我的xUnit测试。 我使用的是xUnit 1.9和Async CTP 1.3。 这是我的测试用例

我有一个接口,它指定一个异步方法调用

public interface IDoStuffAsync { Task AnAsyncMethod(string value); } 

我有一个消耗接口并调用异步方法的类

 public class UseAnAsyncThing { private readonly IDoStuffAsync _doStuffAsync; public UseAnAsyncThing(IDoStuffAsync doStuffAsync) { _doStuffAsync = doStuffAsync; } public async Task DoThatAsyncOperation(string theValue) { await _doStuffAsync.AnAsyncMethod(theValue); } } 

在我的测试中,我希望检查方法DoThatAsyncOperation是否使用正确的值调用方法,因此我模拟了接口并使用Moq来validation调用

  [Fact] public async void The_test_will_pass_even_though_it_should_fail() { var mock = new Mock(); var sut = new UseAnAsyncThing(mock.Object); mock.Setup(x => x.AnAsyncMethod(It.IsAny())); await sut.DoThatAsyncOperation("test"); // This won't throw a Moq.MockExcpetion so the test appears to pass // However it does not run mock.Verify(x => x.AnAsyncMethod("fail")); } 

此测试使用asyncawait关键字。 当它运行时,它错误地通过,因为Moq应断言validation失败。 调用sut.DoThatAsyncOperation("test");后的任何代码sut.DoThatAsyncOperation("test"); 不运行

  [Fact] public void This_will_work_and_assert_the_reslt() { var mock = new Mock(); var sut = new UseAnAsyncThing(mock.Object); mock.Setup(x => x.AnAsyncMethod(It.IsAny())); sut.DoThatAsyncOperation("test").ContinueWith(y => { }); // This won't throw a Moq.MockExcpetion so the test appears to pass // However it does not run mock.Verify(x => x.AnAsyncMethod("fail")); } 

此测试是在没有await和async关键字的情况下设置的,并且传递正常。

这是xUnit和Moq的预期行为吗?


更新

感谢Stephen的评论,我设法通过进行两次更改来修复第一个测试。 测试现在返回一个Task而不是void,Mock也返回一个Task。

  [Fact] public async Task The_test_will_pass_even_though_it_should_fail() { var mock = new Mock(); var sut = new UseAnAsyncThing(mock.Object); mock.Setup(x => x.AnAsyncMethod(It.IsAny())).ReturnAsync(true); await sut.DoThatAsyncOperation("test"); // This now fails as it should mock.Verify(x => x.AnAsyncMethod("fail")); } 

更改unit testing方法以返回Task而不是void ,它应该工作。 正在考虑对将来的版本支持async voidunit testing。

我详细描述了为什么异步unit testing在我的博客上默认不起作用 。 (我的博客示例使用MSTest,但每个其他测试运行器都存在相同的问题,包括xUnit pre-1.9)。

我尝试使用“更新”中的代码,但它停止在我正在嘲笑的异步方法中。

  var tcs = new TaskCompletionSource(); tcs.SetResult(default(T)); mock.Setup(x => x.AnAsyncMethod(It.IsAny())).Returns(tcs.Task); 

所以要解决这个问题我必须改变’Return’方法:

  mock.Setup(x => x.AnAsyncMethod(It.IsAny())).Returns(()=> { return tcs.Task; } );