如何测试数据库中是否创建了一条记录?
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.False
到 Assert.IsFalse
和 True 相同。
- 此示例使用 MySQL,但可以针对任何引擎进行修改。例如,对于 Npgsql (PostgreSQL),将
MySqlCommand
更改为 NpgsqlCommand
并将 MySqlDataReader
更改为 NpgsqlDataReader
.
我来自 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.False
到Assert.IsFalse
和 True 相同。 - 此示例使用 MySQL,但可以针对任何引擎进行修改。例如,对于 Npgsql (PostgreSQL),将
MySqlCommand
更改为NpgsqlCommand
并将MySqlDataReader
更改为NpgsqlDataReader
.