使用 xunit 返回 null 的模拟 HttpClient 包装器
Mocked HttpClient wrapper returning null with xunit
我正在尝试习惯使用 .net Core 进行单元测试。不幸的是,我一直坚持让我的 HttpClient
包装器 return 失败 HttpResponseMessage
。
这是我正在努力进行的测试:
[Fact]
public async void TestHttpExceptionOnBadRequest()
{
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("Test")))
{
var xmlSerializer = new Mock<IXmlSerializer>();
xmlSerializer.Setup(serializer => serializer.Deserialize(stream)).Returns(new object());
var httpClient = new Mock<IHttpHandler>();
httpClient.Setup(client => client.GetAsync("Test"))
.Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadRequest)));
var postcodeLookup = new PostcodeLookupService(xmlSerializer.Object, httpClient.Object, "", "");
await Assert.ThrowsAsync<HttpRequestException>(async () => await postcodeLookup.SearchAsync("", ""));
}
}
以下是我的服务代码。问题是 response.EnsureSuccessStatusCode();
return 为空。
public async Task<PostcodeContainer> SearchAsync(string text, string container)
{
// add the query parameters to the query string
var query = _baseQueryString + "&text=" + WebUtility.UrlEncode(text);
query += "&container=" + WebUtility.UrlEncode(container);
// initiate client & response
var response = await _httpClient.GetAsync(query);
response.EnsureSuccessStatusCode();
return (PostcodeContainer)_serializer.Deserialize(await response.Content.ReadAsStreamAsync());
}
为了完整起见,这里是我的 IHttpHandler
定义,用于模拟目的。
public interface IHttpHandler
{
HttpResponseMessage Get(string url);
HttpResponseMessage Post(string url, HttpContent content);
Task<HttpResponseMessage> GetAsync(string url);
Task<HttpResponseMessage> PostAsync(string url, HttpContent content);
}
那是因为预期的查询设置与被测方法中生成的不匹配。
// add the query parameters to the query string
var query = _baseQueryString + "&text=" + WebUtility.UrlEncode(text);
query += "&container=" + WebUtility.UrlEncode(container);
这会导致模拟 return null
,因为当它收到与 "Test"
.
不匹配的意外查询时,它不知道该怎么做
因此假设 _baseQueryString
也是一个空字符串,基于示例中的测试,生成的查询可能最终为
&text=&container=
因此,为了按预期执行,模拟应该期望收到什么。还考虑到被测方法预计会在序列化程序执行任何操作之前出错,因此无需将其设置为执行任何操作。只是模拟它并通过模拟。
您还可以通过在设置表达式中使用 It.IsAny<string>()
让客户端期待任何查询。
最后,测试 return Task
if performing acync functions
[Fact]
public async Task TestHttpExceptionOnBadRequest() {
var xmlSerializer = new Mock<IXmlSerializer>();
xmlSerializer
.Setup(serializer => serializer.Deserialize(It.IsAny<Stream>()))
.Returns(new PostcodeContainer());
var expectedResponse = new HttpResponseMessage(HttpStatusCode.BadRequest);
var httpClient = new Mock<IHttpHandler>();
httpClient
.Setup(client => client.GetAsync(It.IsAny<string>()))
.ReturnsAsync(expectedResponse);
var postcodeLookup = new PostcodeLookupService(xmlSerializer.Object, httpClient.Object, "", "");
await Assert.ThrowsAsync<HttpRequestException>(async () => await postcodeLookup.SearchAsync("", ""));
}
我正在尝试习惯使用 .net Core 进行单元测试。不幸的是,我一直坚持让我的 HttpClient
包装器 return 失败 HttpResponseMessage
。
这是我正在努力进行的测试:
[Fact]
public async void TestHttpExceptionOnBadRequest()
{
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes("Test")))
{
var xmlSerializer = new Mock<IXmlSerializer>();
xmlSerializer.Setup(serializer => serializer.Deserialize(stream)).Returns(new object());
var httpClient = new Mock<IHttpHandler>();
httpClient.Setup(client => client.GetAsync("Test"))
.Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadRequest)));
var postcodeLookup = new PostcodeLookupService(xmlSerializer.Object, httpClient.Object, "", "");
await Assert.ThrowsAsync<HttpRequestException>(async () => await postcodeLookup.SearchAsync("", ""));
}
}
以下是我的服务代码。问题是 response.EnsureSuccessStatusCode();
return 为空。
public async Task<PostcodeContainer> SearchAsync(string text, string container)
{
// add the query parameters to the query string
var query = _baseQueryString + "&text=" + WebUtility.UrlEncode(text);
query += "&container=" + WebUtility.UrlEncode(container);
// initiate client & response
var response = await _httpClient.GetAsync(query);
response.EnsureSuccessStatusCode();
return (PostcodeContainer)_serializer.Deserialize(await response.Content.ReadAsStreamAsync());
}
为了完整起见,这里是我的 IHttpHandler
定义,用于模拟目的。
public interface IHttpHandler
{
HttpResponseMessage Get(string url);
HttpResponseMessage Post(string url, HttpContent content);
Task<HttpResponseMessage> GetAsync(string url);
Task<HttpResponseMessage> PostAsync(string url, HttpContent content);
}
那是因为预期的查询设置与被测方法中生成的不匹配。
// add the query parameters to the query string
var query = _baseQueryString + "&text=" + WebUtility.UrlEncode(text);
query += "&container=" + WebUtility.UrlEncode(container);
这会导致模拟 return null
,因为当它收到与 "Test"
.
因此假设 _baseQueryString
也是一个空字符串,基于示例中的测试,生成的查询可能最终为
&text=&container=
因此,为了按预期执行,模拟应该期望收到什么。还考虑到被测方法预计会在序列化程序执行任何操作之前出错,因此无需将其设置为执行任何操作。只是模拟它并通过模拟。
您还可以通过在设置表达式中使用 It.IsAny<string>()
让客户端期待任何查询。
最后,测试 return Task
if performing acync functions
[Fact]
public async Task TestHttpExceptionOnBadRequest() {
var xmlSerializer = new Mock<IXmlSerializer>();
xmlSerializer
.Setup(serializer => serializer.Deserialize(It.IsAny<Stream>()))
.Returns(new PostcodeContainer());
var expectedResponse = new HttpResponseMessage(HttpStatusCode.BadRequest);
var httpClient = new Mock<IHttpHandler>();
httpClient
.Setup(client => client.GetAsync(It.IsAny<string>()))
.ReturnsAsync(expectedResponse);
var postcodeLookup = new PostcodeLookupService(xmlSerializer.Object, httpClient.Object, "", "");
await Assert.ThrowsAsync<HttpRequestException>(async () => await postcodeLookup.SearchAsync("", ""));
}