1

我使用 xUnit 和 FluentAssertions 编写单元测试,但遇到以下问题。由于我还没有实现catch(in GetCountriesAsync) 的,我在这个地方WebException扔了一个新的。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 Taskvoid并且测试仍然表现相同,所以我怀疑 asyncAction不能等待,它们相当被解雇和遗忘。

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

4

2 回答 2

1

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

于 2013-04-22T18:50:32.640 回答
0

Regarding FluentAssertions, I've added the following to my code:

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);
        }
    }
}

and now you can do:

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

whereas _teste.Wait<T> returns a Task<T>. Also the naming of the method Awaiting make sense, because pure invocation of the method will not result in the exception being caught by the caller, you do need to use await to do so.

于 2014-07-29T12:56:00.190 回答