4

Currently I am struggeling with some unit tests that run fine from within visual studio but fail in Teamcity

I tracked down the problem to mstests.exe

Let's say I do the following steps:

  1. Create a new Test project
  2. Add a new Test class with the following test

    [TestMethod]
    public void TestCanCreateSqLiteConnection()
    {
        // Create the DbProviderFactory
        var factory = DbProviderFactories.GetFactory("System.Data.SQLite");
        // Create the DbConnection.
        var connection = factory.CreateConnection();
        // Assign connection string
        connection.ConnectionString = "Data Source=database.sqlite";
        // check the result
        Assert.IsTrue(connection.GetType().Name.Equals("SQLiteConnection"));
    }
    
  3. Add an app.config file and add this:

    <system.data>
      <DbProviderFactories>
    
        <remove invariant="System.Data.SQLite" />
        <add name="SQLite Data Provider"
             invariant="System.Data.SQLite"
             description=".Net Framework Data Provider for SQLite"
             type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
    
      </DbProviderFactories>
    </system.data>
    
  4. Install "System.Data.SQLite (x86/x64)" via nuget

  5. Run test from Visual Studio (2010). It should run fine:

Now I want to run the same test via mstest.exe so I:

  1. Open a Visual Studio 2010 command prompt

  2. Navigate to the bin\debug folder

  3. Execute

    mstest.exe /testcontainer:TestProject1.dll /detail:errormessage
    
  4. The test eventually failes with

    System.DllNotFoundException: Unable to load DLL 'SQLite.Interop.DLL':
    The specified module could not be found. (Exception from HRESULT:0x8007007E)
    
  5. Now if I extend the call to mstest.exe with testsettings the test runs fine.

    mstest.exe /testcontainer:TestProject1.dll /detail:errormessage 
        testsettings:..\..\..\Local.testsettings
    

The Local.testsettings contains nothing special, even if I create a new testsettings file and use this, the test passes.

    <?xml version="1.0" encoding="UTF-8"?>
    <TestSettings id="fc837936-41d1-4987-8526-34f9336569f5" name="TestSettings1" enableDefaultDataCollectors="false" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
      <Description>default test run</Description>
      <Deployment enabled="false"/>
    </TestSettings>

So the main question is, why this has an impact on my test run, and how I can run my tests form commandline without specifying a *.testsettings file.

Charles
  • 50,943
  • 13
  • 104
  • 142
Jürgen Steinblock
  • 30,746
  • 24
  • 119
  • 189
  • Two months later, I am having the same issue. Any updates? – kcnygaard Nov 22 '13 at 15:16
  • I changed my TeamCity setup to include this default Local.testsettings file, so no solution. However the main problem seems to be the way how SQLite loads the VC-Runtime. Try different binaries from the download page: http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki (statically linked or the other one) – Jürgen Steinblock Nov 28 '13 at 09:54

4 Answers4

2

You need to use a DeploymentItem to ensure the file is copied to the deployment directory when testing via the command line. I created a base class for all of my test classes that depend on the SQLite database.

[TestClass]
[DeploymentItem("Resources\\empty-db.sqlite", "Resources")]
[DeploymentItem("x64\\SQLite.Interop.dll", "x64")]
[DeploymentItem("x86\\SQLite.Interop.dll", "x86")]
public class SQLiteTest
{
    [TestInitialize()]
    public void ClearDatabase()
    {
        File.Copy("Resources\\empty-db.sqlite", "test-db.sqlite", true);
    }
}
Brian Heilig
  • 592
  • 4
  • 16
1

I encountered a similar error message a while back. If I remember correctly, the following was the crux of the issue: (it may not be 100% relevant for the OP, but it might be useful to somebody who hits this down the line).

The problem was that my unit tests all failed in Release mode with an exception complaining about the availability (or lack thereof) of the SQLite.Interop.dll. I realised that when built in Debug mode, the bin\Debug folder had 2 sub folders (x64 and x86) each with a copy of SQLite.Interop.dll but, in Release mode these files/folders did not exist.

To resolve it, I created the x64 and x86 folders in my project and added the appropriate version of SQLite.Interop.dll too them, setting the Copy to ouput setting to Copy if newer. (I had originally used 'Copy always' but it seems the MS Test engine doesn't shut down when the test run is complete - which can lock the file. Since the dll shouldn't change regularly the Copy if newer option was a suitable approach).

This enabled my unit tests to pass in release mode - but unfortunately (as in the OP's case) they did not work when run from the command line. Still trying to figure that one out - I think it's because MSTest is 32-bit and SQLite uses native code which is (maybe) 64-bit but the finer detail necessary to resolve this eludes me at present.

amcdermott
  • 1,565
  • 15
  • 23
1

Two year later and it is still a pain to get SQLite working in unit tests.

Yesterday I included the current SQLite nuget package into a unit test project with <Deployment enabled="true"/> enabled and could not access sqlite by the dbproviderfactories method.

I included the SQLite interop directories with

<Deployment>
  <DeploymentItem filename="packages\System.Data.SQLite.Core.1.0.98.1\build\net40\" />
</Deployment>

But that was not enough. Accessing the provider with

DbProviderFactories.GetFactory("System.Data.SQLite");

still threw an error Failed to find or load the registered .Net Data Provider error unless I made this call var factory = new System.Data.SQLite.SQLiteFactory(); After that I could acces SQLite witht the DbProviderFactories.

I included this in the ClassInitialize method so is is only executed once.

Jürgen Steinblock
  • 30,746
  • 24
  • 119
  • 189
0

I've encountered a similar issue where the tests run through fine in Visual Studio 2013 but if run directly by MSTest many would fail. No SQL Lite used!

In the end I just added a default .testsettings file to the MSTest call and now the results are consistant.

TS.
  • 381
  • 6
  • 13