DeploymentItem在单独的程序集中中断EntityFramework单元测试

awh*_*rth 6 .net c# unit-testing entity-framework

我在我的解决方案5个集:A,B,B.Test,CC.Test.B并且C都引用A(并且不互相引用).B.Test引用AB,C.Test引用AC.

B.Test,我正在创建一个EntityFramework6 DbContext对象B:

[TestMethod]
public void TestB() {
    MyBContext c = new MyBContext();
}
Run Code Online (Sandbox Code Playgroud)

C.Test,我有一个空的单元测试与DeploymentItem:

[TestMethod]
[DeploymentItem("data.txt")]
public void TestC() { }
Run Code Online (Sandbox Code Playgroud)

当我分别运行两个测试时,它们都通过了.但是,当我将"全部运行"两个测试作为同一测试运行的一部分时,TestB失败并出现以下异常:

"无法加载在具有不变名称'System.Data.SqlClient'的ADO.NET提供程序的应用程序配置文件中注册的实体框架提供程序类型'System.Data.Entity.SqlServer.SqlProviderServices,EntityFramework.SqlServer'.确保使用了程序集限定名称,程序集可供正在运行的应用程序使用.有关详细信息,请参阅http://go.microsoft.com/fwlink/?LinkId=260882."

当我更改TestC注释DeploymentItem属性时如下:

[TestMethod]
//[DeploymentItem("data.txt")]
public void TestC() { }
Run Code Online (Sandbox Code Playgroud)

这两项测试,现在通过.TestB创建上下文而不抛出异常.不知何故,在DeploymentItemAttributein程序集中添加C.Test是打破了一个不在DeploymentItem单独的程序B.Test集中C.Test使用的测试(我在其中使用DeploymentItem 进行其他测试,因此删除这一个实例不会从库中删除引用).我花了很多时间甚至将故障缩小到目前为止,我完全不知道接下来要做什么才能解决这个问题.

编辑:我在MSDN上找到了一些似乎可以解决这个问题的信息(虽然我不明白为什么).

  1. 通过Resharper测试运行器或其他测试运行器运行单元测试似乎解决了这个问题.只有当我通过VisualStudio(2012,如果重要)运行单元测试时,测试才会失败
  2. 将以下代码添加到我的程序集中定义DbContext似乎解决了这个问题:

    static MyDbContext () {
        var _ = typeof(System.Data.Entity.SqlServer.SqlProviderServices);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    (MSDN上的答案建议将此添加到上下文类本身,我将其添加到该上下文的Factory类型,而具有相同的有益结果).

所以看起来我们有一个答案"如何使我的单元测试工作?" 但问题不在于"为什么这首先发生?" 我怀疑,根据这个解决方案,EF6在动态加载类型和程序集时会快速松散,并且在从某些类型的地方执行测试时,某些程序集不会被加载.

Geo*_*Geo 8

问题是由于编译器没有输出EntityFramework.SqlServer.dll,因为它没有检测到它是否在某处使用(它只用于依赖注入).最简单的解决方案是在测试中使用其中一种类型的程序集.

例如,您可以创建一个属性或方法(您不需要使用它,只需将其暴露为公共就足够了).为了解决这个问题,我在测试助手中创建了一个属性:

public static System.Data.Entity.SqlServer.SqlProviderServices EnsureAssemblySqlServerIsCopied { get; set; }
Run Code Online (Sandbox Code Playgroud)


Art*_*ers 1

其原因在于 EF 及其提供者之间的松散耦合以及 MSTest 运行测试的方式。

\n\n

关于提供者,实体框架可以与各种不同的提供者一起工作。SQL Server 提供程序只是一个示例。EntityFramework.dll 对 SQL Server 提供程序集没有硬依赖性,因为将 EF 与任何其他提供程序一起使用时不需要它。

\n\n

这意味着在使用 EF 时,您应该确定将使用哪个提供程序,并确保提供程序程序集与您的应用程序或测试一起部署。这通常是通过将提供程序 NuGet 包安装到应用程序或测试项目中来完成的。如果 NuGet 包安装到应用程序/测试项目中,则提供程序程序集将被放置到 bin 文件夹中,无论代码中是否直接引用它。如果提供程序 NuGet 包仅安装到解决方案中的某些其他项目(例如类库)而不是直接安装到应用程序/测试项目中,则情况并非如此。

\n\n

由于历史原因,SQL Server 提供程序是在主实体框架 NuGet 包中提供的,因此对于 SQL Server 提供程序来说,需要在应用程序/测试项目中安装 EntityFramework 包。如果您不\xe2\x80\x99 不想将提供程序/EntityFramework 包安装到应用程序/测试项目中,那么您可以设置一些其他逻辑以确保程序集已部署。

\n\n

现在,使用 MSTest 事情变得更加棘手,因为它有自己的部署规则和配置。这意味着仅安装 NuGet 包可能还不够,您可能需要设置特定的 MSTest 部署规则以确保正确复制程序集。另一个解决方案是不使用 MSTest。在 EF 团队中,我们几年前从 MSTest 切换到 xUnit,自从这样做以来,此类问题少得多。

\n