2017-01-25 1 views
0

Ich habe diesen ControllerC# Unit-Tests - Unable Inhalt aus der IHttpActionResult Antwort-extrahieren

[Route("GeocacheAddressObjectList")] 
    [HttpPost] 
    public async Task<IHttpActionResult> GeocacheAddressObjectList([FromBody] List<GeocacheAddress> addresses) 
    { 
     //check valid addresses 
     if(addresses == null) 
     { 
      return BadRequest("Invalid addresses. The address list object is null!") as IHttpActionResult; 
     } 

     ElasticHelper searchHelper = new ElasticHelper(ConfigurationManager.AppSettings["ElasticSearchUri"]); 
     List<GeocacheAddress> geocodedAddresses = new List<GeocacheAddress>(); 

     // check each address in the addresses list against geocache db 
     foreach (GeocacheAddress address in addresses) 
     { 
      var elasticSearchResult = SearchGeocacheIndex(address); 

      // found a match 
      if (elasticSearchResult.Total != 0) 
      { 
       SearchProperties standardizedAddressSearch = new SearchProperties(); 
       standardizedAddressSearch.Size = 1; 
       standardizedAddressSearch.From = 0; 

       Address elasticSearchResultAddress = elasticSearchResult.Hits.ElementAt(0).Source; 

       // query the standardized key in geocache db 
       standardizedAddressSearch.ElasticAddressId = elasticSearchResultAddress.Standardized.ToString(); 

       // the address is already standardized, return the standardized address with its geocode 
       if (standardizedAddressSearch.ElasticAddressId == "00000000-0000-0000-0000-000000000000") 
       { 
        geocodedAddresses.Add(new GeocacheAddress 
        { 
         Id = address.Id, 
         Street = elasticSearchResultAddress.AddressString, 
         City = elasticSearchResultAddress.City, 
         State = elasticSearchResultAddress.State, 
         ZipCode = elasticSearchResultAddress.Zipcode, 
         Plus4Code = elasticSearchResultAddress.Plus4Code, 
         Country = elasticSearchResultAddress.Country, 
         Latitude = elasticSearchResultAddress.Coordinates.Lat, 
         Longitude = elasticSearchResultAddress.Coordinates.Lon 
        }); 
       } 
       else // perform another query using the standardized key 
       { 
        Address standardizedAddress = StandardAddressSearch(standardizedAddressSearch).Hits.ElementAt(0).Source; 
        if (standardizedAddress == null) 
        { 
         return BadRequest("No standardized address found in geocache database") as IHttpActionResult; 
        } 

        geocodedAddresses.Add(new GeocacheAddress() 
        { 
         Id = address.Id, 
         Street = standardizedAddress.AddressString, 
         City = standardizedAddress.City, 
         State = standardizedAddress.State, 
         ZipCode = standardizedAddress.Zipcode, 
         Plus4Code = standardizedAddress.Plus4Code, 
         Country = standardizedAddress.Country, 
         Latitude = standardizedAddress.Coordinates.Lat, 
         Longitude = standardizedAddress.Coordinates.Lon 
        }); 
       } 
      } 
      else // not found in geocache db, call SmartStreets API 
      { 
       List<Address> address_list = new List<Address>(); 

       using (HttpClient httpClient = new HttpClient()) 
       { 
        //Send the request and get the response 
        httpClient.BaseAddress = new System.Uri(ConfigurationManager.AppSettings["GeocodingServiceUri"]); 
        httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); 

        //Lookup object to perform Geocoding service call 
        var postBody = JsonConvert.SerializeObject(new Lookup() 
        { 
         MaxCandidates = 1, 
         Street = address.Street, 
         City = address.City, 
         State = address.State, 
         ZipCode = address.ZipCode 
        }); 

        var requestContent = new StringContent(postBody, Encoding.UTF8, "application/json"); 

        // Send the request and get the response 
        var response = await httpClient.PostAsync("GeocodeAddressObject", requestContent); 

        if (!response.IsSuccessStatusCode) //error handling 
        { 
         geocodedAddresses.Add(new GeocacheAddress() 
         { 
          Id = address.Id, 
          Error = response.ReasonPhrase 
         }); 

        } 

        Geocode geocodeFromGeocoder = JsonConvert.DeserializeObject<List<Geocode>>(response.Content.ReadAsStringAsync().Result).ElementAt(0); 

        GeocacheAddress geocodedAddress = new GeocacheAddress() 
        { 
         Id = address.Id, 
         Street = geocodeFromGeocoder.CorrectedAddress, 
         City = geocodeFromGeocoder.City, 
         State = geocodeFromGeocoder.State, 
         ZipCode = geocodeFromGeocoder.Zipcode, 
         Plus4Code = geocodeFromGeocoder.Plus4Code, 
         Country = geocodeFromGeocoder.Country, 
         Latitude = geocodeFromGeocoder.Latitude, 
         Longitude = geocodeFromGeocoder.Longitude 
        }; 

        geocodedAddresses.Add(geocodedAddress); 

        // check each geocoded address against geocache db 
        Guid standardized_key; 

        var geocodedAddressResult = SearchGeocacheIndex(geocodedAddress); 

        // found a match 
        if (geocodedAddressResult.Total != 0) 
        { 
         Address standardizedAddress = geocodedAddressResult.Hits.ElementAt(0).Source; 
         standardized_key = standardizedAddress.AddressID; 
        } 
        else // not found, insert geocode into geocache db 
        { 
         Address new_standardized_address = createStandardizedAddress(geocodeFromGeocoder); 
         standardized_key = new_standardized_address.AddressID; 

         address_list.Add(new_standardized_address); 
        } 

        // insert non-standardized address into geocache db 
        Address new_nonstandardized_address = createNonStandardizedAddress(address, standardized_key); 
        address_list.Add(new_nonstandardized_address); 
       } 

       searchHelper.BulkIndex<Address>(address_list, "xxx", "xxx"); 
      } 
     } 
     return Json(geocodedAddresses, new Newtonsoft.Json.JsonSerializerSettings()) as IHttpActionResult; 
    } 

Ich schreibe einen Unit-Test, einen Teil dieser Steuerung zu testen.

Ich möchte die Antwort von der Steuerung mit dem erwarteten Wert vergleichen. Wenn ich das Ergebnis debugge, zeigt es den Inhalt für die Antwort an, aber ich kann Inhalt wie (result.Content) in dem Code nicht verwenden.

Wenn ich versuche, diese Zeile zu verwenden, gibt sie eine Nullantwort zurück.

 var result = await controller.GeocacheAddressObjectList(testGeocacheAddress) as OkNegotiatedContentResult<GeocacheAddress>; 

Tatsächliche Einheit Testcode. Ich würde jede Hilfe schätzen.

[TestMethod] 
    public async Task TestMethod1() 
    { 
     var controller = new GeocachingController(); 

     var testGeocacheAddress = new List<GeocacheAddress>(); 
     testGeocacheAddress.Add(new GeocacheAddress 
     { 
      City = "Renton", 
     }); 

     var result = await controller.GeocacheAddressObjectList(testGeocacheAddress); 

     var expected = GetGeocacheAddress(); 

     Assert.AreEqual(result.Content.City, expected[0].City); 

}

private List<GeocacheAddress> GetGeocacheAddress() 
    { 
     var testGeocacheAddress = new List<GeocacheAddress>(); 
     testGeocacheAddress.Add(new GeocacheAddress 
     { 
      Id = Guid.Empty, 
      Street = "365 Renton Center Way SW", 
      City = "Renton", 
      State = "WA", 
      ZipCode = "98057", 
      Plus4Code = "2324", 
      Country = "USA", 
      Latitude = 47.47753, 
      Longitude = -122.21851, 
      Error = null 
     }); 

     return testGeocacheAddress; 
    } 
+0

Wenn Sie das Schlüsselwort 'as' verwenden, versucht es, das von Ihnen angegebene Objekt in den von Ihnen angegebenen Typ zu konvertieren. Es kann nicht konvertiert und stattdessen null zurückgegeben werden. – Blam

Antwort

3

In Ihrem Gerät zu testen Sie das Ergebnis JsonResult<T>, genauer gesagt JsonResult<List<GeocacheAddress>> wie werfen müssen, ist, was Sie zurückkehren.

var result = await controller.GeocacheAddressObjectList(testGeocacheAddress) as JsonResult<List<GeocacheAddress>>; 

Wenn Sie return Ok(geocodedAddresses) in Ihrem Controller Rückkehr verwendet haben, waren (, wo Sie jetzt den Anruf von Json zurück), dann können Sie auf OkNegotiatedContentResult<List<GeocacheAddress>> geworfen haben.


auch in Ihrem Controller-Code, den Sie brauchen, um die Rückkehr zu IHttpActionResult nicht zu werfen, weil JsonResult<T> bereits, dass implementiert. Die Besetzung ist redundant.

+1

Ihr Vorschlag arbeitete als ein Charme. Vielen Dank für die Antwort. –

1

Das ist ziemlich einfach zu erreichen, Sie müssen nur den Inhalt, den Sie erwarten, in Ihre Komponententestmethode umwandeln.

Beispiel:

Controller:

public class FooController : ApiController 
    { 
     public IHttpActionResult Get() 
     { 
      var foo = "foo"; 
      return Ok(foo); 
     } 
    } 

Unit-Test:

[TestMethod] 
    public void Get_Foo_From_Controller() 
    { 
     var fooController = new FooController(); 
     var result = fooController.Get(); 
     //Here we are casting the expected type 
     var values = (OkNegotiatedContentResult<string>)result; 
     Assert.AreEqual("Foo", values.Content); 
    } 

By the way, ich bemerkte, dass Sie von dem Asynchron-Schlüsselwort in Ihrer Controller-Aktion verwenden, aber ich don‘ Sehen Sie sich das Schlüsselwort abwarten an.

Wenn Sie das async-Schlüsselwort ohne Wartezeit verwenden, erhalten Sie eine Warnung und erhalten eine synchrone-Operation.

Auch müssen Sie nicht Ihre Antwort als IHttpActionResult, Sie könnten etwas tun, wie ich in meinem Beispiel, wickeln Sie Ihre Inhalte in ein Ok (Ihr Inhalt hier) und Sie sind gut zu gehen.

+0

Vielen Dank für Ihr Feedback. Schätze es wirklich. Ich werde das Casting auf IHttpActionResult entfernen und das Schlüsselwort async hinzufügen. –