如何使用 Fluent Assertions 引发异常?

Posted

技术标签:

【中文标题】如何使用 Fluent Assertions 引发异常?【英文标题】:How could I throw an exception using Fluent Assertions? 【发布时间】:2020-05-02 02:36:15 【问题描述】:

我正在使用client 与CloudMQTT API 进行交互。我正在尝试create a user,但在尝试了下面提供的代码后,我无法创建用户。在为这个项目使用 Github 存储库中提供的代码时,我注意到我无法使用 ShouldThrow() 方法(显然它应该由 Fluent Assertions 提供)。

我确实在 *** 上找到了一个 post,它看起来与我遇到的问题非常相似。在问题中提到 FluentAssertions 不支持异步方法。然而,在客户端的示例代码中,我可以看到无论这个事实如何,都使用了ShouldThrow() 方法。

我怎样才能让ShoudldThrow() 工作,或者我什至需要它工作(因为我认为只有在应用单元测试时才应该在此代码中需要它)?

这是迄今为止尝试过的:

public static async void CreateCloudUser(ICloudMqttApi client)

    var users = await client.GetUsers();
    Console.WriteLine($"Creating a user. Current users available: users.Count");
    var expectedUser = new NewUser
    
        Password = $"Guid.NewGuid()",
        Username = $"staging-Guid.NewGuid()",
    ;

    var createUserResponse = await client.CreateUser(expectedUser);
    createUserResponse.IsSuccessStatusCode.Should().BeTrue();

    var actual = await client.GetUser(expectedUser.Username);
    actual.Should().NotBeNull();
    actual.Username.Should().Be(expectedUser.Username);

    //users.Should().Contain(u => u.Username == expectedUser.Username); // <-- This throws an exception as well, but not of importance for this specific question.

    Func<Task> verifyUser = async () => await client.GetUser(expectedUser.Username);
    verifyUser.ShouldThrow<ApiException>() // <-- Not recognized
            .And.StatusCode.Should().Be(HttpStatusCode.NotFound);

    Console.WriteLine($"Created a user. Current users available: users.Count");

在调用方法之前,客户端的定义方式与客户端文档中提供的方式相同:

var client = CloudMqttApi.GetInstance("username", "password");

在执行方法之前和之后,用户计数将导致相同的数字(显然应该增加)。

【问题讨论】:

CreateCloudUser是测试方法还是被测方法? 这是我自己写的定制方法。它包含在 Github 存储库中找到的测试方法下方提供的相同代码(或至少应该工作相同)。 @Nkosi 【参考方案1】:

鉴于所示代码的异步特性,语法应该是

//...

var deleteResponse = await client.DeleteUser(expectedUser.Username);
deleteResponse.IsSuccessStatusCode.Should().BeTrue();

Func<Task> verifyUser = async () => await client.GetUser(expectedUser.Username);

var exceptionAssertion = await verifyUser.Should().ThrowAsync<ApiException>();
exceptionAssertion.And.StatusCode.Should().Be(HttpStatusCode.NotFound);

//...

参考FluentAssertions: Exceptions

同时避免使用async void。让函数返回Task

public static async Task CreateCloudUser(ICloudMqttApi client) 

    //...


参考Async/Await - Best Practices in Asynchronous Programming

【讨论】:

我正在使用默认控制台应用程序作为此问题的示例。当我试图在 Program 类的 main 方法中调用 CreateCloudUser(client); 时,编译器会抱怨没有等待调用这一事实。当我等待该方法时,编译器会抱怨主方法不是异步方法?还是我应该将此主要方法也设为异步任务方法? 修复这个问题显然并不能解决无法创建用户的问题。不过确实有帮助。 @Barrosy,您可以选择将Main 设为异步方法并等待调用,或者调用CreateCloudUser(...).Wait();,这将阻止执行直到CreateCloudUser 返回。您真正需要做的是了解异步是如何工作的,它的复杂性在哪里,以及如何/在哪里适当地使用它(它不是“神奇的性能果汁”)。 我认为它与异步有关,我不知道您评论中的 .Wait() 部分。 @Tullo_x86 。这真的很有帮助。 @Barrosy 检查答案中添加的链接以了解更多信息

以上是关于如何使用 Fluent Assertions 引发异常?的主要内容,如果未能解决你的问题,请参考以下文章

如果使用 Fluent Assertions 的顺序不同,如何断言两个列表不等价

使用 Fluent Assertions 库的多个断言

Fluent-ASsertions ShouldRaisePropertyChangeFor 不适用于异步任务?

Fluent Assertions:大致比较一个类的属性

Fluent Assertions:两个数组列表的等价性,数组需要严格排序

NUnit 或 Fluent Assertions 测试引用是不是相等?