2013-02-26 3 views
1

적어도 .net 4.5 및 Silverlight 5를 대상으로하는 휴대용 클래스 라이브러리가 있습니다. 라이브러리가 없기 때문에 VS 2012에 MSTest 유닛 테스트를 작성하는 데 문제가 있습니다. 새로운 async/await 패러다임을 사용하십시오. 이 방법을 테스트 할 수있는 방법이 있습니까?휴대용 클래스 라이브러리를 사용한 비동기 유닛 테스트

public static void Get(string uri, string acceptHeader, Action<string> callback) 
{ 
    var request = (HttpWebRequest)WebRequest.Create(uri); 
    request.Accept = acceptHeader;   

    request.BeginGetResponse(o => 
    { 
     var r = o.AsyncState as HttpWebRequest; 
     try 
     { 
      var response = r.EndGetResponse(o); 
      using (var sr = new StreamReader(response.GetResponseStream())) 
      { 
       callback(sr.ReadToEnd()); 
      } 
     } 
     catch (Exception ex) 
     { 
      throw new WebException(string.Format("Unable to access {0}", uri), ex); 
     } 
    }, request); 
} 

답변

2
을 얼마나되는 다음 당신이 단지 수있는 하루의 끝에 그러나 다음

public static void Get(string uri, string acceptHeader, Action<string> callback) 
{ 
    var request = (HttpWebRequest)WebRequest.Create(uri); 
    request.Accept = acceptHeader;   

    request.BeginGetResponse(o => 
    { 
     try 
     { 
      var response = request.EndGetResponse(o); 
      using (var sr = new StreamReader(response.GetResponseStream())) 
      { 
       callback(sr.ReadToEnd()); 
      } 
     } 
     catch (Exception ex) 
     { 
      throw new WebException(string.Format("Unable to access {0}", uri), ex); 
     } 
    }, null); 
} 

을 수행하는 폐쇄을 사용할 수 있습니다

먼저 async/await을 다시 생각해 보시기 바랍니다. 그것은 미래의 물결입니다. Microsoft.Bcl.Async은 .NET 4.5 및 SL5를 대상으로하는 이식 가능한 라이브러리에 async을 지원합니다.

하지만 당신은 그렇게하지 않으려면, 당신은 여전히 ​​async 단위 테스트 사용할 수 있습니다

[TestMethod] 
public async Task Get_RetrievesExpectedString() 
{ 
    var tcs = new TaskCompletionSource<string>(); 
    var client = new ... // arrange 

    client.Get(uri, acceptHeader, result => 
    { 
    tcs.SetResult(result); 
    }); 
    var actual = await tcs.Task; 

    Assert.AreEqual(expected, actual); 
} 

또는 당신이 원한다면, 당신은 "오래된 학교"를 수행 할 수 있습니다

[TestMethod] 
public void Get_RetrievesExpectedString() 
{ 
    var mre = new ManualResetEvent(initialState: false); 
    string actual = null; 
    var client = new ... // arrange 

    client.Get(uri, acceptHeader, result => 
    { 
    actual = result; 
    mre.Set(); 
    }); 
    mre.WaitOne(); 

    Assert.AreEqual(expected, actual); 
} 
+0

실제로 async/await를 사용할 수는 있지만 * Async 메서드는 PCL의 HttpWebRequest에없는 것 같습니다. 어떻게'Get' 메소드를 바꿀 수 있습니까? – user140550

+0

Task.Factory.FromAsync는 APM을 async/await로 변환하기위한 것입니다. – Aron

+0

그리고이 변환에서 "올바른"방법은 메소드가 콜백 권한으로 보내는 문자열을 반환하도록하는 것입니다. – user140550

2

코드 리팩토링을 거부 할 수 없습니다. 당신은 그래서 여기에

public async static void Get(string uri, string acceptHeader, Action<string> callback) 
{ 
    var request = (HttpWebRequest)WebRequest.Create(uri); 
    request.Accept = acceptHeader;   
    var response = await Task.Factory.FromAsync(
          request.BeginGetRequestStream , 
          request.EndGetRequestStream , 
          uri, 
          null); 
    using (var sr = new StreamReader(response)) 
    { 
     callback(sr.ReadToEnd()); 
    } 
} 

가 좋아 내가 그것을

void Main() 
{ 
    {...} 
    var request = (HttpWebRequest)WebRequest.Create(uri); 
    request.Accept = acceptHeader; 
    var response = await request.DownloadStringTaskAwait(); 
    DoSomeStuff(response); 
} 

// Define other methods and classes here 
public static class HttpWebRequestExtension 
{ 
    public async Task<string> DownloadStringTaskAwait(this HttpWebRequest request) 
    { 
     var response = await Task.Factory.FromAsync<Stream>(
          request.BeginGetRequestStream, 
          request.EndGetRequestStream, 
          null); 
        using (var sr = new StreamReader(response)) 
        { 
         return sr.ReadToEnd(); 
        } 
      } 

} 
+0

귀하의 방법은 PCL로 컴파일됩니까? – user140550

+0

그리고 리팩토링에 감사드립니다. 원래 콜백은 별도의 메소드 였으므로 까마귀가있었습니다. – user140550

+1

당신은'async void'를 피해야합니다. 이 경우 다운로드가 실패 할 경우 오류 처리가 망가집니다. –

관련 문제