【问题标题】:My unit test is not catching an exception within my controller action我的单元测试没有在我的控制器操作中捕获异常
【发布时间】:2016-08-13 04:14:06
【问题描述】:

我有一个单元测试,例如:

[Test]
public void ThingController__Put__when_thing_is_invalid__then__throws()
{
    var controller = this.CreateThingController();

    try
    {
        var r = controller.Put("thing1", this.CreateInvalidThing());
    }
    catch(HttpResponseException hrex) when (hrex.Response.StatusCode == HttpStatusCode.BadRequest)
    {
        return; // implicit pass.
    }
    catch(Exception ex)
    {
        Assert.Fail($"Wrong exception {ex.GetType().Name}");
    }

    Assert.Fail("No exception thrown!");
}

但它总是命中最后一个Fail,即不会抛出异常。我已经打开了第一次机会异常,并且可以看到它被抛出并且一直被重新抛出。它肯定一直在冒泡。

注意:SO 将其标记为可能的重复

Unit testing async method for specific exception

这个问题是一个方法,但这个问题是一个问题解决方案,特别是为什么 catch 没有被击中,即你知道怎么做,但是犯了一个常见的错误,忘记了动作是异步的 - 因为他们通常没有Async 后缀 - 并且需要展开。

【问题讨论】:

标签: c# unit-testing async-await


【解决方案1】:

如果您的 Put 方法是异步任务方法,我怀疑它是基于您所描述的问题,您可以修改您的测试方法以通过使签名异步任务适当地处理异步/等待。如果您的 Put 方法是异步任务,它会作为热任务执行,但由于当前没有等待它,您的单元测试线程会在实际引发异常之前继续运行。本质上,原始代码是在创建一个“一劳永逸”的场景。

[Test]
public async Task ThingController__Put__when_thing_is_invalid__then__throws()
{
    var controller = this.CreateThingController();

    try
    {
        var r = await controller.Put("thing1", this.CreateInvalidThing());
    }
    catch(HttpResponseException hrex) when (hrex.Response.StatusCode == HttpStatusCode.BadRequest)
    {
        return; // implicit pass.
    }
    catch(Exception ex)
    {
        Assert.Fail($"Wrong exception {ex.GetType().Name}");
    }

    Assert.Fail("No exception thrown!");
}

【讨论】:

  • 注意:最近的测试框架支持这一点,但如果在一个旧项目上工作,您可能仍需要检查您的版本。
【解决方案2】:

Put 操作方法是异步的吗?

如果是这样,那么您没有访问操作的结果,并且异常没有被“解包”。

如果是IHttpActionResult,您应该调用r.ExecuteAsync(...),或者在Put(...) 的调用下添加r.Wait();。

您可能还需要更改您的 catch 块以捕获 AggregateException 并检查它。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-22
  • 2012-12-14
  • 2018-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多