【问题标题】:xUnit exceptions failsxUnit 异常失败
【发布时间】:2016-09-20 01:26:58
【问题描述】:

我不知道为什么我的单元测试失败了: 被测方法:

public async Task<MyType> Get(string externalId)
{
    if (externalId == null)
        throw new ArgumentNullException();
    if (externalId == "" || externalId == " ")
        throw new FormatException();
        // ...
}

单元测试:

Action action = async () => await controller.Get(null);

// Act & Assert
action.ShouldThrow<ArgumentNullException>();

并且有失败,因为错误消息说:

预计会抛出 ArgumentNullException,但没有抛出任何 execption。

这很奇怪,因为在调试这个测试时抛出了异常行!

我正在使用 xunit 和 fluentasserttions。

【问题讨论】:

  • 为什么你的单元测试包含你的产品代码?我怀疑你复制并粘贴了错误的东西。请提供minimal reproducible example
  • 您不是在等待操作,因此即使发生异常也不会被观察到。使用 Func 代替 Action 并等待它,然后将观察到异常。
  • @MartinCostello 谢谢。

标签: c# xunit


【解决方案1】:

这行是问题所在:

Action action = async () => await controller.Get(null);

它创建了一个async void 方法,这使得观察异常变得极其困难(从而进行适当的测试)。

Last time I checked,Fluent Assertions 只支持“异步”断言的反模式风格:

sut.Awaiting(…).ShouldThrow<T>();

不幸的是,这使用了阻塞同步异步 hack,所以当与单线程 SynchronizationContext 一起使用时,它是 bound to fail。哦,猜猜which unit testing framework provides a single-threaded SynchronizationContext?如果您猜中了 xUnit,那么您将获得奖品。

因此,“异步”FA 测试不适用于开箱即用的 xUnit。你有几个选择。

您可以通过在线程池线程上运行整个测试来避免 xUnit 的上下文;这是低效的,但可以完成工作:

await Task.Run(() =>
{
  controller.Awaiting(c => c.Get(null)).ShouldThrow<ArgumentNullException>();
});

不完全漂亮。

或者,您可以使用自己的异步兼容断言,例如the one I wrote

await AsyncAssert.ThrowsAsync<ArgumentNullException>(() => controller.Get(null));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    • 2019-04-06
    • 2015-12-27
    • 2015-07-25
    • 2016-04-14
    • 1970-01-01
    相关资源
    最近更新 更多