【问题标题】:How to mock Dapper using SQL Connection如何使用 SQL 连接模拟 Dapper
【发布时间】:2021-02-25 03:41:23
【问题描述】:

我正在尝试为存储库编写单元测试用例。我正在努力使用 SQL 连接来模拟 dapper。

我的方法:

public IEnumerable<TestModal> TestMethod(int id)
{
    var spName = "sp_Test";
    var spParams = new
        {
            ID= id
        };

    using (var connection = new SqlConnection(_configuration.GetConnectionString("TestDB")))
    {
        connection.Open();
        return connection.Query<TestModal>(spName, spParams, commandType: CommandType.StoredProcedure);
    }
}

我正在尝试为上述方法编写单元测试用例。

[TestFixture]
public class TestClassTests
{
    private Mock<IConfiguration> _mockConfiguration;
    private Mock<SqlConnection> _mockSqlCOnnection;
    private ITestRepository _testRepository;
    
    [SetUp]
    public void Setup()
    {
        _mockConfiguration = new Mock<IConfiguration>();
        _mockSqlCOnnection = new Mock<SqlConnection>();            
        _testRepository= new TestRepository(_mockConfiguration.Object);
    }
   
    [Test]
    public void TestMethodTest()
    {           
        _mockSqlCOnnection.SetupDapper(x => x.Query<TestModal>(It.IsAny<string>(), null, null, true, null, null)).Returns(fakeData);

        var result = _testRepository.TestMethod(10);

        Assert.IsNotNull(result);
        Assert.AreEqual(result.Count(), fakeData.Count());
    }
}

【问题讨论】:

  • 旁注:您应该为您的存储过程使用sp_ 前缀。微软有reserved that prefix for its own use (see Naming Stored Procedures),你确实会在未来某个时候冒着名称冲突的风险。 It's also bad for your stored procedure performance。最好只是简单地避免 sp_ 并使用其他东西作为前缀 - 或者根本不使用前缀!
  • 测试是什么意思?也就是说,您的方法中没有可测试的逻辑,即可单元测试。如果您想获得任何价值,您需要使用实际的数据库连接进行集成测试。
  • 模拟具体类是一种代码味道。您可能想要模拟 IDbConnection 而不是 SqlConnection,然后重构您的代码,以便 TestMethod 可以干净地获取实例化的 IDbConnection。
  • 我宁愿使用真正的数据库并使用 github.com/jbogard/Respawngithub.com/v-zubritsky/Reseed 之类的东西(我正在编写后者)。模拟通常会使您的测试变得脆弱,因此当需要测试替身来隔离某些组件时,最好使用存根。查看一篇关于 mocks 问题的文章medium.com/javascript-scene/…

标签: sql-server unit-testing moq dapper


【解决方案1】:

您不应该模拟您的数据库进行单元测试。

数据库是非常复杂的东西,这意味着如果您不使用实际的数据库,无论您模拟它的效果如何,您的测试几乎没有价值。

根据您的存储库逻辑的复杂程度,您可能希望使用更轻量级的数据库提供程序,如 SQLite、LocalDb 等,或使用本地 SQLServer 等实际数据库。

显然,如果您使用与生产环境相同的数据库,您将获得最准确的结果。

有关如何使用 SQLite 进行单元测试的示例,您可以查看 Microsoft 的 article 关于使用 SQLite 和 InMemory 数据库进行单元测试。该文章使用 EF Core,但您应该能够推断以使用与 Dapper 相同的方法。

有关使用真实数据库进行单元测试的更多信息,您可以阅读 Jimmy Bogard 的 article 关于使用 Respawn 进行单元测试的文章。

【讨论】:

  • 这不是特别有用。模拟负责与数据库通信的代码可能有一些好处(例如确保调用正确的存储过程等)。这可以与单元测试(集成测试等)之外的更严格的测试方法一起完成。跨度>
  • 此类测试的价值很小,因为您的实际持久层可能甚至不支持存储过程。您将有效地测试您的模拟。此外,可能部署应用程序的实际服务器上可能缺少存储过程,例如在应用迁移后删除。您的测试会给您带来误报,并且您不知道您的代码在投入生产之前会失败。事实是,无论您如何模拟数据库,您仍然无法获得实际行为。
  • 正确,您不想测试数据库,但您正在测试从数据到实体模型的映射。这里的某种测试是有价值的。
猜你喜欢
  • 1970-01-01
  • 2021-08-13
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-13
  • 2015-06-02
相关资源
最近更新 更多