C# 数据访问层的最小起订量

C# 数据访问层的最小起订量,c#,moq,dapper,C#,Moq,Dapper,我有一个控制器。从我调用的地方(BLL的DI)到业务逻辑层(BLL)。我从BLL通过另一个接口调用数据访问层(DAL) DAL层构造函数与DBContext实例一起注入(这里没有注入接口) 因此,通过使用MOQ,我们可以测试控制器、BLL和中间层。但是如何测试DLL层呢 public class DAL():IDAL { private DBEntities entity; public DAL(DBEntities DB) {

我有一个控制器。从我调用的地方(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;
        }
    }
公共类DAL():IDAL
{
私营实体;
公共DAL(DBDB)
{
实体=DB;
}
公开名单
{
var a=SqlMapper.Query(entity.Database.Connection,“”,param,commandType:commandType.StoredProcedure.ToList();
返回a;
}
}

基本上我的问题是如何&在这里模拟什么?这里我们实现了IDA,但我们不在这里注入它。

您可以在测试类的构造函数中模拟并创建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();
        }
}
public类SomeTests:IDisposable
{
公开考试
{
var options=new DbContextOptionsBuilder()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.选择;
_dbContext=newmycontext(选项);
_dbContext.Database.EnsureDeleted();
_dbContext.Database.recreated();
//您可以在此处提供更多设置
}
公共空间处置()
{
_dbContext?.Dispose();
}
}

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

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

如果您想测试您的业务逻辑并需要模拟您的数据访问层,那么模拟是非常有用的!因此,请使用您的方法创建一个接口:

public interface IDAL
{
    List<string> ABC();
}
公共接口
{
列出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();
var dataAccessMock=new Mock();
Setup(x=>x.ABC())。返回(新列表{“ABC”、“DEF”、“GHI”});
//获取一个可以注入/使用的IDAL实例
var mockedInstance=dataAccessMock.Object;
//获取模拟列表
var list=mockedInstance.ABC();

它实际上是工作单元模式。在构造函数中,我们注入了实体框架对象,以避免创建多个对象。在public ABC()中,您可以看到实现。当我们使用它在Dapper方法中传递Dbcontext连接对象时,让我们直接提出我的问题。如果我必须moq一个方法,在那里我注入了DB实体,怎么做?确实,我试过这样做,但这里的拦截器是当我从单元测试传递的模拟数据,方法命中真实数据库时,我需要从mocked那里得到它。我已经编辑了这个方法,希望它清晰。这里的主要障碍是没有依赖注入发生在任何接口上。因此,我们无法模拟层来测试任何方法。因此,在这种情况下,它不会影响真正的ABC()方法。它只会绕过代码。那就不是锻炼了,对吧?我们假设模拟依赖关系&传递给方法,但这是我们的想法。否则你为什么会有DataAccessLayer呢?如果你想模拟你的
DBEntities
你希望返回它的
Database.Connection
属性什么?您还必须模拟
SqlMapper.Query()
方法,这有什么好处?实际上这是我的问题。如果我们不能模拟Dbentites,那么我们就不能在这里提供模拟连接。在本例中,我试图模拟SQlmapper.Query(),但它的抛出错误是:1)因为SQlmapper是一个静态类;2)如果我以某种方式强制编写查询,它会说在SQlmapper中找不到查询。优点是,如果我们的单元测试使用Mock对象命中真实的方法,那么我们将获得更好的代码覆盖率。我能在这里得到任何帮助吗?我看不出有什么好处。你的函数很简单。它从数据库返回数据。为了测试这一点,您需要模拟它的所有对象,这些对象允许与数据库通信。我看不出有什么有价值的测试。在这里,我宁愿使用真实的数据库编写集成测试,并检查其返回的数据是否符合预期格式。不要让自己成为代码覆盖率指标的奴隶。