xUnit和Moq不支持异步
我试图发现如何将异步和等待关键字应用到我的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来验证呼叫
[Fact]
public async void The_test_will_pass_even_though_it_should_fail()
{
var mock = new Mock<IDoStuffAsync>();
var sut = new UseAnAsyncThing(mock.Object);
mock.Setup(x => x.AnAsyncMethod(It.IsAny<string>()));
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"));
}
此测试使用async
和await
关键字。 当它运行时,它会错误地通过,因为Moq应该断言验证失败。 调用sut.DoThatAsyncOperation("test");
后的任何代码sut.DoThatAsyncOperation("test");
不运行
[Fact]
public void This_will_work_and_assert_the_reslt()
{
var mock = new Mock<IDoStuffAsync>();
var sut = new UseAnAsyncThing(mock.Object);
mock.Setup(x => x.AnAsyncMethod(It.IsAny<string>()));
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<IDoStuffAsync>();
var sut = new UseAnAsyncThing(mock.Object);
mock.Setup(x => x.AnAsyncMethod(It.IsAny<string>())).ReturnAsync(true);
await sut.DoThatAsyncOperation("test");
// This now fails as it should
mock.Verify(x => x.AnAsyncMethod("fail"));
}
改变你的单元测试方法返回Task
而不是void
,它应该工作。 未来版本正在考虑支持async void
单元测试。
我详细描述了为什么异步单元测试在我的博客上默认不起作用。 (我的博客示例使用MSTest,但每个其他测试运行者都存在相同的问题,包括xUnit 1.9之前的版本)。
我尝试使用'更新'中的代码,但它停止在我嘲笑的异步方法中。
var tcs = new TaskCompletionSource<T>();
tcs.SetResult(default(T));
mock.Setup(x => x.AnAsyncMethod(It.IsAny<T>())).Returns(tcs.Task);
所以要解决这个问题,我必须改变'Return'方法:
mock.Setup(x => x.AnAsyncMethod(It.IsAny<T>())).Returns(()=> { return tcs.Task; } );
链接地址: http://www.djcxy.com/p/35337.html