2014-02-27 83 views
1

我正在從一個外部webservice API檢索信息的項目,但我不知道我應該如何測試它,我在測試方面很新,而且我只做了幾個單元測試,但據我所知,我不得不嘲笑web服務功能,我一直在尋找關於這個主題的信息,但還沒有發現任何Windows Phone的東西。這些類型的案件的標準程序是什麼?如何在Windows Phone上使用Webservice的單元測試方法?

這裏是什麼,我想測試一個簡單的版本:

public async Task<List<Song>> FetchSongsAsync(String query) 
    { 
     if (String.IsNullOrEmpty(query)) 
      return null; 

     string requestUrl = "webservice url"; 
     var client = new HttpClient(); 
     var result = await client.GetStringAsync(new Uri(requestUrl,UriKind.Absolute)); 
     try 
     { 
      var result = JsonConvert.DeserializeObject<RootObject>(result); 
      return result; 
     } 
     catch (Exception) 
     { 
      return null; 
     } 
    } 

謝謝!

回答

1

Decouple代碼從它的依賴:使內容加載和反序列化其replaceable

private readonly IClient client; 
private readonly ISerializer serializer; 

public YourService(IClient client, ISerializer serializer) 
{ 
    _client = client; 
    _serializer = serializer; 
} 

public async Task<List<Song>> FetchSongsAsync(String query) 
{ 
    try 
    { 
     var result = await _client.GetStringAsync(new Uri("http://example.com")); 
     return _serializer.DeserializeObject<RootObject>(result); 
    } 
    catch (Exception) 
    { 
     return null; 
    } 
} 
+0

感謝這有助於=),只是一件事情,如果我還想測試HttpClient上的異常,就像404異常例如 –

+0

@edua_glz:然後模擬'_client'拋出的http異常。假設使用'new Mock ().Setup(c => c.Get(It.IsAny ())。拋出()'。 – abatishchev

0

可能有助於理解和使用依賴注入的第一件事。基本上取決於你的對象/方法/等的任何依賴關係和(因爲它說)將它們注入對象/方法/等。例如,您很難弄清楚如何測試該方法,因爲該方法依賴於能夠訪問Web服務。在此之後你可以做幾件事情。

要做的一件事就是檢查模擬框架,如Moq

我最近做的另一件事是我添加了一個重載的構造函數(依賴注入),需要一個HttpMessageInvoker對象(注意HttpClient派生自此)。這樣一來,我可以用我自己的響應消息實例化類:

public class MyLoader() 
{ 
    protected HttpMessageInvoker MessageInvoker { get; set; } 
    private HttpRequestMessage requestMessage; 

    public MyLoader() // default constructor 
    { 
     MessageInvoker = new HttpClient(); 
    } 

    public MyLoader(HttpMessageInvoker httpMessageInvoker) 
    { 
     MessageInvoker = httpMessageInvoker; 
    } 

    public object DoSomething() 
    { 
     var response = await MessageInvoker.SendAsync(requestMessage, cancellationTokenSource.Token); 
    } 

這裏是我的模擬信息調用:

public class MockMessageInvoker : HttpMessageInvoker 
{ 
    public string ResponseString { get; set; } 

    public MockMessageInvoker(string responseString) 
     : base(new HttpClientHandler()) 
    { 
     ResponseString = responseString; 
    } 

    public override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) 
    { 
     return Task.Run<HttpResponseMessage>(() => 
     { 
      HttpResponseMessage responseMessage = new HttpResponseMessage(
       System.Net.HttpStatusCode.OK); 

      var bytes = Encoding.ASCII.GetBytes(ResponseString); 
      var stream = new System.IO.MemoryStream(bytes); 

      responseMessage.Content = new StreamContent(stream); 
      return responseMessage; 
     }); 

    } 
} 

我可以把它所有像這樣:

MyLoader loader = new MyLoader(new MockMessageInvoker(validJsonResponse)); 
loader.DoSomething() // I've removed the dependency on the service and have control of the content in the response 

這是快速和骯髒,但伎倆。

希望這會有所幫助。

+0

爲什麼代碼存根,而不是用諷刺框架嘲笑它,如起訂量? – abatishchev

+0

請注意,這也是我在那裏拋出的可能解決方案之一。 Moq具體。 – earthling

+0

當然,我很抱歉,錯過了。我會嘲笑(少代碼)而不是扼殺(更多代碼)。當然是 – abatishchev