【问题标题】:No result returned when calling async local request in a Unit Test在单元测试中调用异步本地请求时没有返回结果
【发布时间】:2019-03-03 01:37:55
【问题描述】:

你能看出我遗漏了什么明显的东西吗?我正在尝试创建一个调用本地 web api 的单元测试,但我没有得到预期的结果。

我使用的文章资源是here

[TestMethod]
public void TestAutocomplete()
{

    string resource = "api/products?parm=test";

    Task<Class1> product = GetProductAsync(resource);
}
async Task<Class1> GetProductAsync(string path)
{
    HttpClient client = new HttpClient();
    // Update port # in the following line.
    client.BaseAddress = new Uri("http://localhost:22292/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json"));
    HttpResponseMessage response = await client.GetAsync(path);
    Class1 product = null;
    if (response.IsSuccessStatusCode)
    {
        product = await response.Content.ReadAsAsync<Class1>();
    }
    return product;
}

...

public class Class1
{
    public string text { get; set; }
    public string street_line { get; set; }
    public string city { get; set; }
    public string state { get; set; }
}

更新: 更改后:

Task<Class1> product = GetProductAsync(resource);

Class1 product = GetProductAsync(resource).Result;

{"无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型 'AddressValidationAPI.Tests.Class1' 因为该类型需要 JSON 对象(例如 {\"name\":\"value\"})正确反序列化。\r\n修复 此错误要么将 JSON 更改为 JSON 对象(例如 {\"name\":\"value\"}) 或将反序列化类型更改为数组或 实现集合接口的类型(例如 ICollection、IList) 比如可以从 JSON 数组反序列化的 List。 JsonArrayAttribute 也可以添加到类型中以强制它 从 JSON 数组反序列化。\r\n路径 '',第 1 行,位置 1。"}

【问题讨论】:

  • 您遇到了什么问题?出乎意料的是什么?代码运行完全一样。如果您想在不使方法异步的情况下执行该任务,请使用.Result
  • 我希望填充 Class1 产品,但它是上面显示的图像。没有地址信息返回。
  • 因为您正在返回一个任务。它不是一个产品。您需要执行该任务。要么将方法切换到异步并使用等待,要么使用GetProductAsync(resource).Result
  • @LukeVo,我尝试了 .Result 并得到错误...请参阅底部的 OP。
  • 请将请求结果显示为原始 JSON。您可能会发现它以[ 开头,它只能反序列化为一个集合(如错误消息所述)。 ReadAsync&lt;List&lt;Class1&gt;&gt;()也是如此。

标签: c#


【解决方案1】:

感谢 OP 下的所有 cmets。这是最终的单元测试。谢谢大家。

[TestMethod]
public void TestAutocomplete()
{
    string resource = "api/addresses";
    List<AutocompleteSuggestions> suggests = GetAutocompleteSuggestions(resource).Result;
    Assert.AreEqual(1, suggests.Count);
}
async Task<List<AutocompleteSuggestions>> GetAutocompleteSuggestions(string path)
{
    using (HttpClient httpClient = new HttpClient())
    {
        httpClient.BaseAddress = new Uri("http://localhost:22292/");
        httpClient.DefaultRequestHeaders.Accept.Clear();
        httpClient.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));
        HttpResponseMessage response = await httpClient.GetAsync(path);
        List<AutocompleteSuggestions> suggests = null;
        if (response.IsSuccessStatusCode)
        {
            suggests = await response.Content.ReadAsAsync<List<AutocompleteSuggestions>>();
        }
        return suggests;
    }
}

【讨论】:

    【解决方案2】:

    注意Task&lt;Class1&gt; GetProductAsync 不返回Class1(注意你应该正确命名它),而是一个Task&lt;Class1&gt;,并且你没有任何代码来执行它来获得结果。

    您必须通过推荐的正确方式执行它:

    [TestMethod]
    public async Task TestAutocomplete()
    {
        string resource = "api/addresses";
        List<AutocompleteSuggestions> suggests = await GetAutocompleteSuggestions(resource);
        Assert.AreEqual(1, suggests.Count);
    }
    

    另一个小提示,也建议将GetAutocompleteSuggestions 重命名为GetAutocompleteSuggestionsAsync,这样你就知道你应该等待它。

    如果您绝对不能将其切换到异步方法(例如,在 Main 方法中 - 最近也支持,或者当您的测试框架不支持它时),请使用:

    List<AutocompleteSuggestions> suggests = GetAutocompleteSuggestions(resource).Result;
    

    进一步参考:Asynchronous programming with async and await (C#)

    后一个错误只是您的 JSON/模型类中的错误结构。您只需要在两者之间进行检查和协调即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-23
      • 1970-01-01
      • 2022-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多