gpt4 book ai didi

c# - 集成测试共享数据库的多个 Entity Framework dbcontexts

转载 作者:行者123 更新时间:2023-11-30 14:55:03 25 4
gpt4 key购买 nike

在我的应用程序中,我有多个小型 Entity Framework dbcontexts,它们共享同一个数据库,例如:

public class Context1 : DbContext {
public Context1()
: base("DemoDb") {
}
}

public class Context2 : DbContext {
public Context2()
: base("DemoDb") {
}
}

所有数据库更新都是通过脚本完成的,不依赖于迁移(以后也不会)。问题是 - 您将如何针对这些上下文进行集成测试?

我相信这里有三个选项(可能还有更多我只是不知道)

选项 1 - super 上下文 - 包含设置数据库所需的所有模型和配置的上下文:

public class SuperContext : DbContext
{
public SuperContext()
: base("DemoDb") {
}
}

在此选项中,测试数据库将针对 super 上下文进行设置,所有后续测试将通过较小的上下文完成。我不喜欢这个选项的原因是我将复制我已经构建的所有配置和实体模型。

选项 2 - 为集成测试创建自定义初始化程序,它将运行所有适当的数据库初始化脚本:

public class IntegrationTestInitializer : IDatabaseInitializer<DbContext> {

public void InitializeDatabase(DbContext context) {
/* run scripts to set up database here */
}
}

此选项允许针对真实的数据库结构进行测试,但每次添加新的数据库脚本时也需要更新

选项 3 - 仅测试各个上下文:

在此选项中,您只需让 EF 根据上下文创建测试数据库,所有测试都将在其自己的“沙箱”中运行。我不喜欢它的原因是,它不会让人觉得您会针对数据库的真实表示进行测试。

我目前倾向于选项 2。你们怎么看?有没有更好的方法?

最佳答案

我经常使用集成测试,因为我仍然认为它是涉及数据相关流程时最可靠的测试方法。我也有几个不同的上下文,以及用于数据库升级的 DDL 脚本,所以我们的情况非常相似。

我最终得到的是选项 4:通过常规用户界面维护单元测试数据库内容。当然,大多数集成测试临时修改数据库内容,作为测试“行动”阶段的一部分(稍后将详细介绍这个“临时”),但内容是测试 session 开始时未设置。

这就是原因。

在某个阶段,我们还在测试 session 开始时通过代码或通过反序列化 XML 文件生成数据库内容。 (我们还没有 EF,否则我们可能会在数据库初始化程序中使用一些 Seed 方法)。渐渐地,我开始对这种做法产生疑虑。当数据模型或业务逻辑发生变化时,维护代码/XML 是一项艰巨的工作,尤其是。当必须设计新的用例时。有时我允许自己对这些测试数据进行轻微损坏,因为我知道这不会影响测试。

此外,数据必须有意义,因为它们必须与来自实际应用程序的数据一样有效和连贯。确保这一点的一种方法是通过应用程序本身生成数据,否则您将不可避免地以某种方式在种子方法中复制业务逻辑。 模拟真实世界的数据实际上非常困难。这是我发现的最重要的事情。测试不代表真实用例的数据群不仅是浪费时间,而且是虚假的安全措施。

因此,我发现自己通过应用程序的前端创建测试数据,然后煞费苦心地将此内容序列化为 XML 或编写生成完全相同的代码。直到有一天我突然想到,我在这个数据库中有现成的数据,为什么不直接使用它呢?

现在您可能会问如何使测试独立?

集成测试,就像单元测试一样,应该是独立执行的。它们不应依赖于其他测试,也不应受其影响。我假设您的问题的背景是您为每个集成测试创建并播种了一个数据库。这是实现独立测试的一种方式。

但是如果只有一个数据库,没有种子脚本怎么办?您可以为每个测试恢复备份。我们选择了不同的方法。每个集成测试都在从未提交的 TransactionScope 中运行。这是很容易实现的。每个测试夹具都继承自具有这些方法 (NUnit) 的基类:

[SetUp]
public void InitTestEnvironment()
{
SetupTeardown.PerTestSetup();
}

[TearDown]
public void CleanTestEnvironment()
{
SetupTeardown.PerTestTearDown();
}

SetupTeardown 中:

public static void PerTestSetup()
{
_tranactionScope = new TransactionScope();
}

public static void PerTestTearDown()
{
if (_tranactionScope != null)
{
_tranactionScope.Dispose(); // Rollback any changes made in a test.
_tranactionScope = null;
}
}

其中 _tranactionScope 是一个静态成员变量。

关于c# - 集成测试共享数据库的多个 Entity Framework dbcontexts,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26257366/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com