检查 FluentAssertion 异常语法中的返回值

Posted

技术标签:

【中文标题】检查 FluentAssertion 异常语法中的返回值【英文标题】:Check return value in FluentAssertion exception syntax 【发布时间】:2019-06-03 04:33:18 【问题描述】:

我想通过 FluentAssertion 语法检查方法的返回值。请考虑以下 sn-p:

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

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

【问题讨论】:

您正在捕获并吞下异常,因此无需检查。一旦异常被捕获,它将返回 17 是的,因为这是一个简化的示例。这段代码的目的是展示我的需求。 是的,但第一次测试没有任何意义。第二个测试的成功完成意味着异常被捕获,所以没有什么可以组合或检查 【参考方案1】:

当前版本的 Fluent Assertions (5.5.3) 不区分 Func&lt;Task&gt;Func&lt;Task&lt;T&gt;&gt;。 这两种类型都由AsyncFunctionAssertions 处理,它将其分配给Func&lt;Task&gt;,因此丢失了Task&lt;T&gt; 的返回值。

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

[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&lt;T&gt; 的支持,因此您可以继续对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);

【讨论】:

以上是关于检查 FluentAssertion 异常语法中的返回值的主要内容,如果未能解决你的问题,请参考以下文章

FluentAssertion : 用私有内部对象列表断言对象相等

异常处理

如何使用 FluentAssertion 编写 CustomAssertion?

FluentAssertion - 向 if 语句添加断言

如何创建自定义 FluentAssertion 错误消息?

使用 FluentAssertion 时 Visual Studio 警告 CA1806 的错误识别(不要忽略方法结果)