2017-04-06 33 views
1

我想要習慣單元測試.net核心。不幸的是,我堅持讓我的HttpClient包裝返回失敗的HttpResponseMessageMocked HttpClient包裝返回null與xunit

這裏是我的測試,我試圖讓工作:

[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();返回null。

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); 
} 

回答

2

這是因爲預期的查詢設置與被測方法中生成的不匹配。

// add the query parameters to the query string 
var query = _baseQueryString + "&text=" + WebUtility.UrlEncode(text); 
query += "&container=" + WebUtility.UrlEncode(container); 

這將導致模擬返回null,因爲它不知道什麼時候它得到意想不到的查詢不匹配​​做什麼。

因此,假設_baseQueryString也是基於測試一個空字符串在本例中生成的查詢可能最終成爲

&text=&container= 

因此是模擬應該會收到以達到預期效果的。此外,考慮到在序列化器執行任何操作之前,測試中的方法可能會出錯,所以不需要設置它來執行任何操作。只是嘲笑它並通過模擬。

您還可以通過在設置表達式中使用It.IsAny<string>()來讓客戶端期待任何查詢。

最後,有測試返回Task如果執行acync功能

[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("", "")); 
}