Task.Wait始终返回false,尽管任务已完成

时间:2017-04-27 09:26:30

标签: c# unit-testing asp.net-web-api async-await owin

我正在使用HttpClient尝试在Web API控制器中执行POST方法。控制器方法是同步的。我是这样做的:

var response = owin.HttpClient.PostAsJsonAsync(uri, body);

之后我打电话给Wait

var result = response.Wait(15000);

运行此代码时,我看到http结束执行,但result值始终为false。我能错过什么?

编辑: 我现在尝试了异步方法,但它也没有帮助我

public IHttpActionResult Add(Item item)
{
    var result = _db.AddItem(item);
    return Ok(result);
}

测试项目:

TestServer _owinTestServer;
public async Task<HttpResponse message> Method1(string url, object body)
{
    return await 
   _owinTestServer.HttpClient.PostAsJsonAsync(url,body);
}

public async Task<ItemPreview> Method2(object body);
{
     return await Method1("..", body ).Result.Content.ReadAsAsync<ItemPreview>();
}

[TestMethod]
public void test1()
{
    Item item = new(...);
    Method2(item).Continue with(task => {// Never reach     here }
}

我做错了什么? 在调试时,我看到控制器方法返回了一个很好的响应,但它永远不会回到我的测试

4 个答案:

答案 0 :(得分:10)

您正在混合异步和阻止调用(即Dialog.Result),这会导致死锁。

这看起来更像是测试客户端的阻塞问题。

如果你想等待来自服务器的结果,你需要在这种情况下让测试完全异步。

将测试方法转换为异步

.Wait()

并更新方法,不要混合异步和阻止调用。

[TestMethod] public async Task test1() { //Arrange Item item = new Item(...); //Act var preview = await Method2(item); //Assert Assert.IsNotNull(preview); } 如果在调用后没有使用任务,则不需要Method1,因此可以将其删除并让方法返回可以等待的asyn/await

Task

TestServer _owinTestServer; public Task<HttpResponse> Method1(string url, object body) { return _owinTestServer.HttpClient.PostAsJsonAsync(url, body); } 需要Method2来自await的回复,然后获取其内容。

Method1

答案 1 :(得分:0)

控制器方法是否同步无关紧要。这纯粹是对服务器代码的关注。由于PostAsJsonAsync方法是异步的,因此您需要await它:

var response = await owin.HttpClient.PostAsJsonAsync(uri, body);

这将允许您的代码等待来自服务器的响应。

答案 2 :(得分:0)

我假设您的初始代码看起来像这样......

activities

是的,等待15秒后结果将是假的。这是因为您已经设置了请求A.K.A响应,但您实际上没有进行被调用和任何响应.Wait(n)将返回false。

您只需要启动ReadAsAsync ...

var categoryList = document.querySelector('#categories');

for (var i = 0; i < activitiesArray.sections.length; i++) {
    categoryList.innerHTML += "<li><span>" + 
activitiesArray.sections[i].category + "</span></li>";
}

--
var activitiesArray = {
    sections : [
    {
        category: "Winter Activities",
        activities: [
            "Snowboarding", "Snowmobiling", "Ice Skating", "Snow Tubing", "Figure Skating", "Sledding", "Luge", "Bobsleigh", "Polar Plunge", "Ice Fishing", "Skiing"
        ]
    },
    {
        category: "Music",
        activities: [
            "Music Festival", "Concert", "Live Music", "Opera", "Symphony", "Jam Session", "Learn an Instrument", "Musical Theatre"
        ]
    }
  ]
}

但是,我认为你会发现你可以跳过响应。等等(全部),因为它将返回true,因为ReadAsAsync()将等待返回或失败。如果您正在寻找配置请求超时,您可以在HttpClient中执行此操作,并且您的ReadAsAsync将抛出一个AggregateException,其InnerException为TaskCanceledException。

另外,您不需要使用owin.HttpClient就可以实例化一个新的HttpClient。我相信你所指的owin对象是自我托管你的WebApi,我不知道这是否重要。但是,假设您在WebApi上调用Add(Item项)并且db.AddItem(item)将返回和ItemPreview对象,您的代码可能如下所示:

var response = owin.HttpClient.PostAsJsonAsync(uri, body);
var result = response.Wait(15000);
var itemPreview = response.Result.Content.ReadAsAsync<ItemPreview>();
...

答案 3 :(得分:0)

结果可能始终为false,因为_db.AddItem始终返回false。如果没有,我已经对你的代码进行了理想的更改,哪些应该对你有用

TestServer _owinTestServer;
public async Task<HttpResponse message> Method1(string url, object body)
{
    return await _owinTestServer.HttpClient.PostAsJsonAsync(url,body);
}

public async Task<ItemPreview> Method2(object body);
{
     return await Method1("..", body ).Result.Content.ReadAsAsync<ItemPreview>();
}

[TestMethod]
public void test1()
{
    Item item = new(...);
    await Method2(item).ContinueWith(task => {// Never reach     here }
}

由于Method2返回Async Task,ContinueWith将不会等待它完成,因此在方法调用时可能需要等待