检查 FluentAssertion 异常语法中的 return 值

Check return value in FluentAssertion exception syntax

我想通过 FluentAssertion 语法检查方法中的 return 值。请考虑以下代码段:

public interface IFoo
{
    Task<int> DoSomething();
}

public class Bar
{
    private readonly IFoo _foo;
    private static int _someMagicNumber = 17;

    public Bar(IFoo foo)
    {
        _foo = foo;
    }

    public async Task<int> DoSomethingSmart()
    {
        try
        {
            return await _foo.DoSomething();
        }
        catch
        {
            return _someMagicNumber;
        }
    }
}

[TestFixture]
public class BarTests
{
    [Test]
    public async Task ShouldCatchException()
    {
        // Arrange
        var foo = Substitute.For<IFoo>();
        foo.DoSomething().Throws(new Exception());
        var bar = new Bar(foo);
        Func<Task> result = () => bar.DoSomethingSmart();

        // Act-Assert
        await result.Should().NotThrowAsync();
    }

    [Test]
    public async Task ShouldReturnDefaultValueWhenExceptionWasThrown()
    {
        // Arrange
        var foo = Substitute.For<IFoo>();
        foo.DoSomething().Throws(new Exception());
        var bar = new Bar(foo);

        // Act
        var result = await bar.DoSomethingSmart();

        // Assert
        result.Should().Be(17);
    }
}

我的目标是将这两个测试合并到新的测试中,但我想保留流畅的断言检查:result.Should().NotThrowAsync();

所以我的问题是如何在我的示例中检查 return 值为 17 的第一个测试?

当前版本的 Fluent Assertions (5.5.3) 不区分 Func<Task>Func<Task<T>>。 这两种类型都由 AsyncFunctionAssertions 处理,它将其分配给 Func<Task> 并因此失去 Task<T>.

的 return 值

避免这种情况的一种方法是将 return 值分配给局部变量。

[Test]
public async Task ShouldCatchException()
{
    // Arrange
    var foo = Substitute.For<IFoo>();
    foo.DoSomething().Throws(new Exception());
    var bar = new Bar(foo);

    // Act
    int? result = null;
    Func<Task> act = async () => result = await bar.DoSomethingSmart();

    // Act-Assert
    await act.Should().NotThrowAsync();
    result.Should().Be(17);
}

我在 Fluent Assertion 问题跟踪器上创建了一个 issue

编辑:

Fluent Assertions 6.0.0 添加了对 Task<T> 的支持,因此您可以继续对 DoSomethingSmart.

的结果进行断言
// Arrange
var foo = Substitute.For<IFoo>();
foo.DoSomething().Throws(new Exception());
var bar = new Bar(foo);

// Act
Func<Task<int>> act = () => bar.DoSomethingSmart();

// Act-Assert
(await act.Should().NotThrowAsync()).Which.Should().Be(17);

还有一个新的简洁助手 WithResult 用于异步方法以避免额外的括号集。

// Arrange
var foo = Substitute.For<IFoo>();
foo.DoSomething().Throws(new Exception());
var bar = new Bar(foo);

// Act
Func<Task<int>> act = () => bar.DoSomethingSmart();

// Act-Assert
await act.Should().NotThrowAsync().WithResult(17);