2016-10-17 5 views
-3

Ich habe eine Menge schwerer Modifikationen an einem asynchronen Code vorgenommen, und ich habe lange genug daran herumgebastelt, dass ich eine zweite Reihe von Augen brauche.Async Warte beim Generieren einer Null-Ausnahme beim Testen

In einem Komponententest rufe ich meinen asynchronen Code auf und validiere dann die Werte, die zurückgegeben werden sollen. Das Objekt, das letztendlich die asynchrone Operation ausführt, wird gespottet.

Die Einheit Test:

public void GetCharactersAsync_ById_Test() 
    { 
     var charDictionary = TestHelper.GetCharactersIdDictionary(1); 
     var mockReq = new Mock<IRequester>(); 
     mockReq.Setup(x => x.CreateGetRequestAsync<Dictionary<long, Character>> 
          (It.IsAny<string>())).ReturnsAsync(charDictionary); 
     var char1 = TestHelper.GetCharacter(); 
     var api = GameObject.GetInstance(mockReq.Object); 

     var character = api.GetCharacterAsync(TestHelper.GetRegion(), (int)char.Id); 

     Assert.AreEqual(character.Result.Name, char1.Name); 
    } 

GetCharacterAsync:

requester.CreateGetRequestAsync (obwohl dies verspottet werden sollte, und egal):

public async Task<T> CreateGetRequestAsync<T>(string urlString) 
    { 
     return await this.GetResultAsyncDeserialized<T>(new HttpRequestMessage(HttpMethod.Get, urlString)); 
    } 

und schließlich GetResultAsyncDeserialized (obwohl dies verspottet und sollte keine Rolle spielen):

protected async Task<T> GetResultAsyncDeserialized<T>(HttpRequestMessage request) 

    { 
     var result = string.Empty; 
     using (var response = await httpClient.GetAsync(request.RequestUri)) 
     { 
      if (!response.IsSuccessStatusCode) 
      { 
       HandleRequestFailure(response.StatusCode); 
      } 
      using (var content = response.Content) 
      { 
       result = await content.ReadAsStringAsync(); 
      } 
     } 
     return JsonConvert.DeserializeObject<T>(result); 
    } 

Ich habe neben null Erfahrung mit async, und dieser Code ist sehr ähnlich wie die alten Arbeits Code in Struktur (I bewegt ein einige Dinge herum, wie der JsonConvert auf die unterste Ebene, wenn es oben war). Die großen Veränderungen waren tatsächlich alle auf der Ebene, die verspottet wird, und sollten den Komponententest nicht beeinflussen. Der Komponententest ist fast identisch mit dem alten (entfernte einige Serialisierung/Deserialisierung).

Exception is a Null Reference Exception on GetCharacterAsync line:

var obj = res.Result.Values.FirstOrDefault(); 
+0

Mögliche Duplikat [Was für eine Nullreferenceexception ist, und wie kann ich es beheben?] (Http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do- i-fix-it) – Igor

+1

Könnten Sie bitte die Exception und Stack-Trace posten? – Andrew

+1

Sie sollten wirklich nicht 'character.Result.Name' machen, den Test' async Task' anstelle von 'void' zurückgeben und' character' erwarten. So gut wie jede Unit-Test-Bibliothek (einschließlich derjenigen, die in Visual Studio integriert ist) unterstützt async/abwarten jetzt. –

Antwort

4

Ihre await requester.CreateGetRequestAsync<Task<Dictionary<long, Character>>> falsch ist, sollten Sie nicht Task in dieser Funktion geben werden, sollte die Methode Unterschrift sein await requester.CreateGetRequestAsync<Dictionary<long, Character>>

public async Task<Character> GetCharacterAsync(Region region, int charId) 
{ 
    var res = await requester.CreateGetRequestAsync<Dictionary<long, Character>> 
        (bld.BuildUrlForEndpoint("GetCharacter", 
        region, charId.ToString())); 
    var obj = res.Values.FirstOrDefault(); 
    return obj; 
} 

Der Grund, warum Sie null werden immer in GetCharacterAsync ist Sie rufen CreateGetRequestAsync<Task<Dictionary<long, Character>>>, aber Ihr moq wurde mit mockReq.Setup(x => x.CreateGetRequestAsync<Dictionary<long, Character>>

eingerichtet

P.S. Als Randnotiz sollten Sie in Ihrem Test wahrscheinlich nicht character.Result.Name machen, den Test async Task statt void zurückgeben und das Ergebnis von api.GetCharacterAsync abwarten. So gut wie jede Unit-Test-Bibliothek (einschließlich derjenigen, die in Visual Studio integriert ist) unterstützt async/abwarten jetzt.

public async Task GetCharactersAsync_ById_Test() 
{ 
    var charDictionary = TestHelper.GetCharactersIdDictionary(1); 
    var mockReq = new Mock<IRequester>(); 
    mockReq.Setup(x => x.CreateGetRequestAsync<Dictionary<long, Character>> 
         (It.IsAny<string>())).ReturnsAsync(charDictionary); 
    var char1 = TestHelper.GetCharacter(); 
    var api = GameObject.GetInstance(mockReq.Object); 

    var character = await api.GetCharacterAsync(TestHelper.GetRegion(), (int)char.Id); 

    Assert.AreEqual(character.Name, char1.Name); 
}