2013-02-26 2 views
1

У меня есть переносимая библиотека классов, для которой требуется указать хотя бы .net 4.5 и Silverlight 5. У меня возникла проблема с попыткой записать модульные тесты MSTest в VS 2012, потому что моя библиотека не используйте новую асинхронную/ожидающую парадигму. Есть ли способ проверить этот метод?Асинхронное тестирование модулей с помощью переносимых библиотек классов

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

Во-первых, я рекомендую вам пересмотреть async/await. Это волна будущего. Microsoft.Bcl.Async обеспечивает поддержку async портативных библиотек, ориентированных на .NET 4.5 и SL5.

Но если вы не хотите, чтобы сделать это, вы все еще можете использовать 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, кажется, отсутствуют в 'HttpWebRequest' для PCL. Как бы вы меняли метод 'Get'? – user140550

+0

Task.Factory.FromAsync предназначен для преобразования APM в async/wait. – Aron

+0

И в этом преобразовании «правильным» способом сделать это было бы, чтобы метод возвращал строку, которую я отправляю в право обратного вызова? – user140550

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

Однако в конце дня вы можете просто сделать следующее

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». В этом случае он беспорядок с вашей обработкой ошибок, если загрузка никогда не срабатывает. –