【发布时间】:2013-07-06 13:09:38
【问题描述】:
我想测试是否从异步方法返回了正确的类型。此方法使用依赖类中的另一个异步方法。依赖类实现了这个接口:
Task<string> DownloadStringAsync(string url);
我要测试的方法是这样的:
public async Task<T> GetData<T>(string url) where T : class , new()
{
var jsonData = await _webClientWrapper.DownloadStringAsync(url);
if (string.IsNullOrEmpty(jsonData))
return new T();
try
{
return await JsonConvert.DeserializeObjectAsync<T>(jsonData);
}
catch (JsonException inner)
{
throw new JsonConvertException("Error converting Json string", inner) { JsonString = jsonData };
}
}
使用 xUnit 和 Moq 测试成功:
public class Testes
{
private const string ValidJson = "{'Nome':'Rogerio','Idade':'51'}";
protected static JsonWebServiceClassProvider JsonWebServiceClassProvider;
private static Mock<IWebClientWrapper> _webClientWrapperMoq;
private static FakeClassFromJson _resultClass;
[Fact]
public async static void When_calling_GetData_it_should_return_a_class_of_same_type()
{
_webClientWrapperMoq = new Mock<IWebClientWrapper>();
_webClientWrapperMoq
.Setup(w => w.DownloadStringAsync(Moq.It.IsAny<string>()))
.Returns(Task.FromResult(ValidJson));
JsonWebServiceClassProvider = new JsonWebServiceClassProvider(_webClientWrapperMoq.Object);
_resultClass = await JsonWebServiceClassProvider
.GetData<FakeClassFromJson>(Moq.It.IsAny<string>());
Assert.IsType<FakeClassFromJson>(_resultClass);
}
}
使用 MSpec 和 Moq 进行测试:
[Subject("JsonWebServiceClassProvider")]
public class When_calling_GetData_with_a_valid_Json_Service_Url
{
private const string ValidJson = "{'Nome':'Rogerio','Idade':'51'}";
protected static JsonWebServiceClassProvider JsonWebServiceClassProvider;
protected static Mock<IWebClientWrapper> WebClientWrapperMoq;
protected static FakeClassFromJson ResultClass;
Establish context = () =>
{
WebClientWrapperMoq = new Mock<IWebClientWrapper>();
WebClientWrapperMoq
.Setup(w => w.DownloadStringAsync(Moq.It.IsAny<string>()))
.Returns(Task.FromResult(ValidJson));
JsonWebServiceClassProvider = new JsonWebServiceClassProvider(WebClientWrapperMoq.Object);
};
Because of = () => ResultClass = JsonWebServiceClassProvider
.GetData<FakeClassFromJson>(Moq.It.IsAny<string>())
.Await();
It should_return_a_class_of_same_type = () => ResultClass.ShouldBeOfType<FakeClassFromJson>();
}
这些Because 语句也会失败
Because of = () => JsonWebServiceClassProvider
.GetData<FakeClassFromJson>(Moq.It.IsAny<string>())
.ContinueWith(task => ResultClass = task.Result)
.Wait();
Because of = () => ResultClass = JsonWebServiceClassProvider
.GetData<FakeClassFromJson>(Moq.It.IsAny<string>())
.Result;
这会失败并在行中显示NullReferenceException
public async Task<T> GetData<T>(string url) where T : class , new()
{
string jsonData = await _webClientWrapper.DownloadStringAsync(url);
// ...
}
已解决
在等待响应时,做了一些重构,瞧!我用Establish 语句创建了一个基类,并在那里启动了模拟对象:
public class JsonWebServiceClassProviderSpecs
{
protected static JsonWebServiceClassProvider JsonWebServiceClassProvider;
protected static Mock<IWebClientWrapper> WebClientWrapperMoq;
Establish context = () =>
{
WebClientWrapperMoq = new Mock<IWebClientWrapper>();
JsonWebServiceClassProvider = new JsonWebServiceClassProvider(WebClientWrapperMoq.Object);
};
}
我更新了测试类:
[Subject("JsonWebServiceClassProvider")]
public class When_ask_data_with_a_valid_Json_Service_Url : JsonWebServiceClassProviderSpecs
{
private const string ValidJson = "{'Nome':'Rogerio','Idade':'51'}";
protected static FakeClassFromJson ResultClass;
Establish context = () =>
{
WebClientWrapperMoq
.Setup(w => w.DownloadStringAsync(Moq.It.IsAny<string>()))
.Returns(Task.FromResult(ValidJson));
};
Because of = () => ResultClass = JsonWebServiceClassProvider
.GetData<FakeClassFromJson>(Moq.It.IsAny<string>())
.Await();
It should_return_a_class_of_same_type = () => ResultClass.ShouldBeOfType<FakeClassFromJson>();
}
【问题讨论】:
-
请发布您的“已解决”更新作为答案,以便我们可以单独对您的解决方案进行投票/评论!
-
如果您是 TekPub 订阅者,Jon Skeet 关于异步 C# 系列的最后一集对单元测试异步代码有一些很好的建议。
-
在阅读了@Alexander Groß 的回复后,我返回了我的原始代码并且它有效。这里的问题是我的代码一直是正确的。但最初和一段时间它因 NullReferenceException 而失败。我一直不明白为什么。
标签: c# moq async-await mspec