如何测试数据库中是否创建了一条记录?

How to test if a record was created in the database?

我来自 Laravel 并且是 ASP.net MVC 的新手。在 Laravel 中,我曾经这样做来断言是否在数据库中创建了一条记录:

public function test_a_user_is_created_in_database()
{
    // Arrange
    // Act

    $this->assertDatabaseHas('users', [
        'email' => 'sally@example.com'
    ]);
}

有没有办法在 Xunit 中完成同样的事情?

这是一个集成测试。

您可能不想进行集成测试,通常在 .net 和单元测试中,您会使用 FakeItEasy 或 Moq 之类的东西来提供正确键入的数据,以便被测代码随与您要在单元测试中测试的场景相匹配的数据。如果您正在测试用户是否在场,您将设置它以便加载数据的调用 return 是适当的响应,如果您正在测试用户在场时发生的情况,您将提供数据和将 return 称为适合您要测试的用户的数据。

在集成 Web 服务时,集成测试可能是合适的,并且您不太确定它会做什么 return,但是如果您使用的是 dbcontext 和 entity framework(以及你可能应该是)然后毫无疑问成功加载用户应该 return.

可能有更优雅的方法来实现目标,但这对我的目的来说效果很好:

public static void AssertDatabaseHas(string table, Dictionary<string, object> filters, 
    bool assertMissing = false) {

    using (MySqlCommand cmd = new MySqlCommand()) {
        cmd.Connection = GetDbConnection();

        // Assemble the WHERE part of the query
        // and add parameters to the command.
        var filterStr = "1 = 1";
        foreach (KeyValuePair<string, object> item in filters) {
            if (string.IsNullOrEmpty(item.Value.ToString())) {
                filterStr += " AND " + item.Key + " IS NULL";
            } else {
                filterStr += " AND " + item.Key + " = @" + item.Key;
                cmd.Parameters.AddWithValue(item.Key, item.Value);
            }
        }

        // Put the query together.
        cmd.CommandText = string.Format("SELECT 1 FROM {0} WHERE {1}", table, filterStr);

        // Execute the query and check the result.
        using (MySqlDataReader rdr = cmd.ExecuteReader()) {
            if (assertMissing) {
                Assert.False(rdr.HasRows, "Undesired record exists.");
            } else {
                Assert.True(rdr.HasRows, "Desired record does not exist.");
            }
        }
    }
}

也很容易添加函数的反向:

public static void AssertDatabaseMissing(string table, Dictionary<string, object> filters) {
    AssertDatabaseHas(table, filters, assertMissing: true);
}

当两者都添加到 MyCustomAssertions class 时,可以这样调用它们:

public void test_a_user_is_created_in_database()
{
    MyCustomAssertions.AssertDatabaseHas("users", new Dictionary<string, object> {
        { "email", "sally@example.com" }
    });

    MyCustomAssertions.AssertDatabaseMissing("users", new Dictionary<string, object> {
        { "email", "sally@example.com" }, { "id", "10" }
    });
}

注:

  • 如果您碰巧使用了 MSTest,那么代码可以很容易地适应它;您需要更改的只是 Assert.FalseAssert.IsFalse 和 True 相同。
  • 此示例使用 MySQL,但可以针对任何引擎进行修改。例如,对于 Npgsql (PostgreSQL),将 MySqlCommand 更改为 NpgsqlCommand 并将 MySqlDataReader 更改为 NpgsqlDataReader.