【问题标题】:Searching for nicer implementation for this unit test为这个单元测试寻找更好的实现
【发布时间】:2013-04-02 10:25:50
【问题描述】:

我使用 xUnit 和 FluentAssertions 编写单元测试,但遇到以下问题。由于我还没有实现WebException 的catch(在GetCountriesAsync 中),所以我在这个地方抛出了一个新的NotImplementedException。

此代码是我使测试按预期实际工作的唯一方法。我也添加了原生 xUnit 实现,因为 FluentAssertions 只是语法糖。

[Fact]
public async Task GetCountriesAsyncThrowsExceptionWithoutInternetConnection()
{
    // Arrange
    Helpers.Disconnect(); // simulates network disconnect
    var provider = new CountryProvider();

    try
    {
        // Act
        var countries = await provider.GetCountriesAsync();
    }
    catch (Exception e)
    {
        // Assert FluentAssertions
        e.Should().BeOfType<NotImplementedException>();

        // Assert XUnit
        Assert.IsType<NotImplementedException>(e);
    }
}

虽然我发现这个实现要好得多,但它就是行不通。

[Fact]
public async Task GetCountriesAsyncThrowsExceptionWithoutInternetConnection3()
{
    // Arrange
    Helpers.Disconnect(); // simulates network disconnect
    var provider = new CountryProvider();

    // Act / Assert FluentAssertions
    provider.Invoking(async p => await p.GetCountriesAsync())
            .ShouldThrow<NotImplementedException>();

    // Act / Assert XUnit
    Assert.Throws<NotImplementedException>(async () => await provider.GetCountriesAsync());
}

由于 VS2012/ReSharper 已经建议删除测试方法的冗余 async 关键字,我将 async Task 替换为 void 并且测试的行为仍然相同,所以我怀疑async Actions 不能等待,他们宁愿被解雇和遗忘。

有没有办法使用 xUnit/FluentAssertions 正确实现这一点?我想我必须使用我的第一个实现,因为我看不到像 InvokingAsync() 这样的任何功能。

【问题讨论】:

标签: unit-testing xunit xunit.net fluent-assertions


【解决方案1】:

实际上,FA 2.0 对处理异步异常有特定的支持。只需查看AsyncFunctionExceptionAssertionSpecs 中的单元测试。各种例子。

【讨论】:

    【解决方案2】:

    关于 FluentAssertions,我在代码中添加了以下内容:

    using System;
    using System.Threading.Tasks;
    
    namespace FluentAssertions
    {
        public static class FluentInvocationAssertionExtensions
        {
            public static Func<Task> Awaiting<T>(this T subject, Func<T, Task> action)
            {
                return () => action(subject);
            }
        }
    }
    

    现在你可以这样做了:

    _testee.Awaiting(async x => await x.Wait<Foo>(TimeSpan.Zero))
            .ShouldThrow<BarException>();
    

    而_teste.Wait&lt;T&gt; 返回Task&lt;T&gt;。 方法Awaiting的命名也很有意义,因为纯调用方法不会导致异常被调用者捕获,你需要使用await来这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-23
      • 1970-01-01
      • 2010-12-17
      • 2011-09-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多