【问题标题】:Moq for the Data Access Layer数据访问层的起订量
【发布时间】:2018-09-20 07:18:16
【问题描述】:

我有一个控制器。从我调用的位置(BLL 的 DI)到业务逻辑层(BLL)。从 BLL 我通过另一个接口调用数据访问层 (DAL)。

DAL 层构造函数被注入了 DBContext 实例(这里没有注入接口)。

因此,通过使用 MOQ,我们可以测试控制器、BLL 和中间层。但是如何测试DLL层呢?

    public class DAL():IDAL
    {
        private DBEntities entity;

        public DAL(DBEntities DB)
        {
            entity = DB;
        }

        public list<string> ABC()
        {
            var a = SqlMapper.Query<class>(entity.Database.Connection, "",param,commandType: CommandType.StoredProcedure).ToList();
            return a;
        }
    }

基本上我的查询如何&在这里模拟什么?这里我们实现了 IDAL,但这里没有注入。

【问题讨论】:

  • 实际上是工作单元模式。在构造函数中,我们注入了实体框架对象以避免创建多个对象。在 public ABC() 你可以看到实现。因为我们使用它在 Dapper 方法中传递 Dbcontext 连接对象。
  • 让我的问题直截了当。如果我必须最小化一个注入数据库实体的方法,该怎么办?
  • 没错,我尝试过这种方式,但这里的障碍是当我从单元测试传递的 Mock 数据、方法到达真实数据库时,我需要从模拟中获取它。
  • 我已经编辑了方法希望它清楚。
  • 这里的主要障碍是任何接口都没有发生依赖注入。所以我们无法模拟层来测试任何方法。

标签: c# moq dapper


【解决方案1】:

这个问题对我来说仍然不是 100% 清楚,但我尝试给出答案。

不需要模拟DBEntities。如果您想确保您的查询返回正确的结果,请使用一个众所周知的预填充数据库进行测试,该数据库仅用于您的测试。

如果您想测试您的业务逻辑并需要模拟您的数据访问层,那么模拟很有帮助!所以用你的方法创建一个接口:

public interface IDAL
{
    List<string> ABC();
}

在您的单元测试中,您可以模拟界面:

var dataAccessMock = new Mock<IDAL>();
dataAccessMock.Setup(x => x.ABC()).Returns(new List<string> {"ABC", "DEF", "GHI" });
// get an IDAL instance which you can inject / use
var mockedInstance = dataAccessMock.Object;
// get the mocked list
var list = mockedInstance.ABC();

【讨论】:

  • 所以在这种情况下,它不会碰到 Real ABC() 方法。它只会绕过代码。那么它不去锻炼对吗?我们假设要模拟依赖并传递给方法。
  • 但这就是想法。那为什么还要有一个 DataAccessLayer 呢?如果您想模拟您的DBEntities,您希望返回其Database.Connection 属性吗?您还必须模拟您的 SqlMapper.Query&lt;&gt;() 方法,这样做有什么好处?
  • 其实这是我的问题。如果我们不能模拟 Dbentites,那么我们就不能在这里模拟 Connection。在这种情况下,我试图模拟 SQlmapper.Query(),但它的抛出错误,1)因为 SQLMapper 是一个静态类,2)如果我以某种方式强行编写 Query,它说 Query not found in SQlMapper。优点是如果我们的单元测试使用 Mock 对象命中真实方法,那么我们将获得更好的代码覆盖率。
  • 我可以在这里得到任何帮助吗?
  • 我没有看到好处。您的函数 ABC 非常简单。它从数据库返回数据。要对此进行测试,您需要模拟所有允许与数据库通信的对象。我看不到任何有价值的测试。在这里,我宁愿用一个真实的数据库编写集成测试,并检查它返回的数据是否符合预期的形式。不要让自己成为代码覆盖率指标的奴隶。
【解决方案2】:

您可以在测试类的构造函数中模拟和创建 InMemoryDb 的 DAL 实例,这将只是您的数据库的一个空架构,而不是使用一些测试所需的数据来传播它,而不是检查您的查询。我就是这样做的。

    public class SomeTests : IDisposable
{
        public SomeTests()
        {
            var options = new DbContextOptionsBuilder<MyContext>()
                .UseInMemoryDatabase(Guid.NewGuid().ToString())
                .Options;

            _dbContext = new MyContext(options);
            _dbContext.Database.EnsureDeleted();
            _dbContext.Database.EnsureCreated();

            // you can provide some more settings here
        }

        public void Dispose()
        {
            _dbContext?.Dispose();
        }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-20
    • 2011-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    相关资源
    最近更新 更多