4

目前,我正在努力解决一些在 Visual Studio 中运行良好但在 Teamcity 中失败的单元测试

我将问题追踪到 mstests.exe

假设我执行以下步骤:

  1. 创建一个新的测试项目
  2. 使用以下测试添加一个新的测试类

    [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. 添加一个 app.config 文件并添加以下内容:

    <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. 通过 nuget 安装“System.Data.SQLite (x86/x64)”

  5. 从 Visual Studio (2010) 运行测试。它应该运行良好:

现在我想通过 mstest.exe 运行相同的测试,所以我:

  1. 打开 Visual Studio 2010 命令提示符

  2. 导航到 bin\debug 文件夹

  3. 执行

    mstest.exe /testcontainer:TestProject1.dll /detail:errormessage
    
  4. 测试最终失败

    System.DllNotFoundException: Unable to load DLL 'SQLite.Interop.DLL':
    The specified module could not be found. (Exception from HRESULT:0x8007007E)
    
  5. 现在,如果我使用 testsettings 扩展对 mstest.exe 的调用,则测试运行良好。

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

Local.testsettings 没有什么特别之处,即使我创建了一个新的 testsettings 文件并使用它,测试也会通过。

    <?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>

所以主要问题是,为什么这会影响我的测试运行,以及如何在不指定 *.testsettings 文件的情况下从命令行运行测试。

4

4 回答 4

2

您需要使用 DeploymentItem 来确保在通过命令行进行测试时将文件复制到部署目录。我为依赖于 SQLite 数据库的所有测试类创建了一个基类。

[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);
    }
}
于 2017-07-14T13:52:03.693 回答
1

不久前我遇到了类似的错误消息。如果我没记错的话,以下是问题的症结所在:(它可能与 OP 没有 100% 的相关性,但它可能对遇到此问题的人有用)。

问题是我的单元测试在发布模式下都失败了,但有一个异常抱怨 SQLite.Interop.dll 的可用性(或缺乏)。我意识到在调试模式下构建时,bin\Debug 文件夹有 2 个子文件夹(x64 和 x86),每个子文件夹都有一个 SQLite.Interop.dll 的副本,但是在发布模式下,这些文件/文件夹不存在。

为了解决这个问题,我在我的项目中创建了 x64 和 x86 文件夹,并为它们添加了适当版本的 SQLite.Interop.dll,将Copy to ouput设置设置为Copy if newer. (我最初使用的是“始终复制”,但似乎 MS 测试引擎在测试运行完成时并未关闭 - 这可以锁定文件。由于 dll 不应定期更改,因此该Copy if newer选项是一种合适的方法)。

这使我的单元测试能够在发布模式下通过 - 但不幸的是(如在 OP 的情况下)它们在从命令行运行时不起作用。仍在尝试解决这个问题 - 我认为这是因为 MSTest 是 32 位的,而 SQLite 使用的是(可能)64 位的本机代码,但目前解决这个问题所需的更精细的细节让我难以理解。

于 2015-04-14T14:22:06.627 回答
1

两年后,让 SQLite 在单元测试中工作仍然很痛苦。

昨天我将当前的 SQLite nuget 包包含到一个单元测试项目中,<Deployment enabled="true"/>启用并且无法通过 dbproviderfactories 方法访问 sqlite。

我包含了 SQLite 互操作目录

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

但这还不够。访问提供者

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

Failed to find or load the registered .Net Data Provider error除非我进行此调用,否则仍然会引发错误var factory = new System.Data.SQLite.SQLiteFactory();之后,我可以使用 DbProviderFactories 访问 SQLite。

我将其包含在ClassInitialize方法中,因此仅执行一次。

于 2015-10-08T05:45:20.157 回答
0

我遇到了一个类似的问题,测试在 Visual Studio 2013 中运行良好,但如果直接由 MSTest 运行,很多会失败。没有使用 SQL Lite!

最后,我只是在 MSTest 调用中添加了一个默认的 .testsettings 文件,现在结果是一致的。

于 2015-06-10T08:20:05.683 回答