DeploymentItem terminates EntityFramework unit test in a separate assembly

I have 5 assemblies in my solution: A , B , B.Test , C and C.Test . B and C both A links (and do not link to each other). B.Test links A and B , C.Test links A and C

In B.Test I create an EntityFramework6 DbContext object defined in B :

 [TestMethod] public void TestB() { MyBContext c = new MyBContext(); } 

In C.Test , I have an empty unit test with DeploymentItem :

 [TestMethod] [DeploymentItem("data.txt")] public void TestC() { } 

When I run two tests separately, they both pass. HOWEVER, When I run all the tests together as part of the same test run, TestB fails with the following exception:

"Entity platform provider type" System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer ', registered in the application configuration file for the ADO.NET provider with the invariant name "System.Data.SqlClient", cannot be loaded. Ensure that the name for the assembly is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for details.

When I modify TestC to comment on the DeploymentItem attribute as follows:

 [TestMethod] //[DeploymentItem("data.txt")] public void TestC() { } 

Both tests pass now . TestB creates a context without exception. Be that as it may, adding a DeploymentItemAttribute in the C.Test assembly interrupts a test that does not use the DeploymentItem in a separate B.Test assembly (And I have other tests in C.Test that use the DeploymentItem, so deleting this instance does not remove the link from the library). It took me a long time to even narrow down the failure so far, and I am completely confused by what even to do to solve this problem.

EDIT: I found some information about MSDN that seems to solve this problem (although I don't understand why).

  • Running unit tests through a Resharper test runner, or another test runner, seems to solve the problem. Only when I run unit tests through VisualStudio (in 2012, if that matters), the tests are not executed
  • Adding the following code to my assembly that defines DbContext seems to fix the problem:

     static MyDbContext () { var _ = typeof(System.Data.Entity.SqlServer.SqlProviderServices); } 

    (The answer to MSDN suggests adding this to the context class itself, I added it to the Factory type for that context instead of the same useful results).

So it looks like we have the answer to the question "how can I get my unit tests to work?" but not the question "why does this happen in the first place?" I suspect that with this solution in mind, EF6 plays a bit quickly and freely when loading types and assemblies dynamically, and some assemblies do not load when tests are run from certain types of places.

+6
source share
2 answers

The reasons for this are due to the decoupling of communication between EF and its providers, as well as the way MSTest runs the tests.

As for providers, Entity Framework can work with various providers. The SQL Server Provider is just one example. EntityFramework.dll is not strictly dependent on the build of the SQL Server provider, since it is not needed when using EF with any other provider.

This means that when using EF, you must determine which vendor (s) will be used and make sure that vendor assemblies are deployed along with your application or tests. This is usually done by installing the NuGet provider package in an application or test project. If the NuGet package is installed in the application / test project, the provider collector will be placed in the bin folder, regardless of whether it refers directly to the code. This is not the case if the NuGet provider package is installed only in some other project in the solution (for example, in the class library), and not directly in the application / testing project.

For historical reasons, the SQL Server provider is sent to the main Entity Framework NuGet, so for the SQL Server provider, this is the EntityFramework package that must be installed in the application / test project. If you do not want to install the provider / EntityFramework package in the application / test project, you can configure other logic to ensure the assembly is deployed.

Now with MSTest, everything is becoming more complicated because it has its own rules and deployment settings. This means that simply installing the NuGet package may not be sufficient, and you may need to configure certain MSTest deployment rules to ensure that the assembly is copied correctly. Another solution is to not use MSTest. In the EF team, we switched from MSTest to xUnit several years ago, and because of this, there were much fewer problems of this kind.

+1
source

The problem arises because the compiler does not output EntityFramework.SqlServer.dll, because it does not detect that it is used somewhere (it is used only for dependency injection). The easiest solution is to use one of the build types inside your test.

eg. You can create a property or method (you don’t need to use it, just exposing it as public). To solve this problem, I created a property inside the test helper:

 public static System.Data.Entity.SqlServer.SqlProviderServices EnsureAssemblySqlServerIsCopied { get; set; } 
+8
source

All Articles