Search code examples
c#unit-testingmstestvstest.console.exemicrosoft-data-sqlclient

Unable to load DLL 'Microsoft.Data.SqlClient.SNI.x86.dll' from Unit Tests when using Microsoft.Data.SqlClient 2.0


When using the Microsoft.Data.SqlClient package (version 2.0) in my code I get the following error when Unit Tests are executed via VSTest.console.exe in our CI provider (and when ran locally):

System.TypeInitializationException: The type initializer for 'Microsoft.Data.SqlClient.TdsParser' threw an exception. ---> System.TypeInitializationException: The type initializer for 'Microsoft.Data.SqlClient.SNILoadHandle' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'Microsoft.Data.SqlClient.SNI.x86.dll': The specified module could not be found

The code executes correctly and unit tests also work fine from NCrunch and the Visual Studio 2019 test runner - so what's the issue?


Solution

  • The issue is that VSTest.Console.exe scans the unit test assemblies for dependencies and copies the results to an output directory for testing.

    Although the Microsoft.Data.SqlClient package dependent package Microsoft.Data.SqlClient.SNI correctly places the Microsoft.Data.SqlClient.SNI.x86.dll and Microsoft.Data.SqlClient.SNI.x64.dll files in the assembly output folder, VSTest.Console.exe doesn't identify them as dependencies automatically and copy them to the testing output folder, so the tests fail.

    My workaround was to explicitly specify the DLLs as deployment items for the tests via a special-purpose test class as follows:

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    
    namespace MyTests
    {
        /// <summary>
        /// Ensures Microsoft.Data.SqlClient dependencies exist for tests.
        /// </summary>
        /// <remarks>
        /// This class performs no tests and is here purely to ensure that the Microsoft.Data.SqlClient.SNI.*
        /// exist for unit testing purposes (specifically when VSTest.Console is used by the build).
        /// This was introduced for Microsoft.Data.SqlClient 2.0.1 and Microsoft.Data.SqlClient.SNI 2.1.0.
        /// Thos packages need to be a package reference on the unit test project.
        /// Later versions may not need this workaround.
        /// </remarks>
        [TestClass]
        [DeploymentItem("Microsoft.Data.SqlClient.SNI.x86.dll")]
        [DeploymentItem("Microsoft.Data.SqlClient.SNI.x64.dll")]
        public class TestSqlClient
        {
            [TestMethod]
            public void TestSqlClient_Test()
            {
            }
        }
    }
    

    This will ensure the DLLs are present for tests. Not ideal but it works!

    Also in case it's useful, this is how I ran VSTest.Console.exe to diagnose this issue:

    VSTest.Console /Diag:D:\Temp\trace.log /ResultsDirectory:D:\Temp\TestResults d:\Repos\YourRepo\YourProject.Tests\bin\Debug\YourProject.Tests.dll