如何使用 Entifty 框架上下文和 Dapper 上下文模拟存储库

问题描述 投票:0回答:2

我正在尝试使用 Moq、xUnit、.Net 6、实体框架核心进行模拟,我有这个存储库:

public class EmployeeRepository : IEmployeeRepository
{
    private readonly DemoContext _context;
    private readonly DapperContext _dapperContext;
    public EmployeeRepository(DemoContext context, DapperContext dapperContext)
    {
        _context = context;
        _dapperContext = dapperContext;
    }
    public async Task<List<EmployeeDTO>> GetAll()
    {
        using (var connection = _dapperContext.CreateConnection()) 
        {
            var employees = await connection.QueryAsync<EmployeeDTO>(
                sql: "usp_get_all_employees",
                commandType: CommandType.StoredProcedure);
            return employees.ToList();
        }
    }
}

这是员工资料库界面:

public interface IEmployeeRepository
{
    Task<List<EmployeeDTO>> GetAll();
}

这是我的 Dapper 上下文:

public class DapperContext
{
    private readonly IConfiguration _configuration;
    private readonly string _connectionString;

    public DapperContext(IConfiguration configuration)
    {
        _configuration = configuration;
        _connectionString = _configuration["connectionStrings:DbContext"];
    }

    public IDbConnection CreateConnection()
    => new SqlConnection(_connectionString);

}

最后,这是我的测试类:

public class EmployeeRepositoryTest
{
    private readonly Mock<DemoContext> _contextMock;
    private readonly Mock<IEmployeeRepository> _employeeRepositoryMock;
    private readonly Mock<DapperContext> _dapperContextMock;
    private readonly Mock<IConfiguration> _mockConfig;
    public EmployeeRepositoryTest()
    {
        _employeeRepositoryMock = new Mock<IEmployeeRepository>();
        _dapperContextMock = new Mock<DapperContext>();
        _mockConfig = new Mock<IConfiguration>();
    }        

    [Fact]
    public async void GetAllEmployeesShouldWorks()
    {
        //arrange
        var options = new DbContextOptionsBuilder<DemoContext>()
            .UseInMemoryDatabase(databaseName: "DemoApp")
            .Options;

        var EmployeeEntity = new Employee();
        EmployeeEntity.Name = "Test Employee";
        EmployeeEntity.Id = Guid.NewGuid();
        EmployeeEntity.DateAdmission = DateTime.Now;
        EmployeeEntity.CompanyId = Guid.NewGuid();

        using (var context = new DemoContext(options))
        {
            context.Add(EmployeeEntity);
            await context.SaveChangesAsync();
        }


        using (var context = new DemoContext(options))
        {


            //Act
            var employeeRepository = new EmployeeRepository(context, _dapperContextMock.Object);//here is the exceptioon
            var employees = await employeeRepository.GetAll();

            //Assert
            Assert.NotNull(employees);
        }
    }
}

但在注释“//exception here”的行中出现此消息错误:“System.ArgumentException:'无法实例化类的代理:Data.Context.DapperContext。 找不到无参数的构造函数。 (参数'constructorArguments')'“

我同时拥有(实体框架和 dapper),因为我正在使用 CQRS,并且我有用于查询的 dapper 和用于命令的 EF。 任何可能的解决方案?提前致谢。

c# unit-testing async-await moq .net-6.0
2个回答
0
投票

你只是忘了在 Arrange 阶段设置模拟

_companyRepositoryMock
   .Setup(r => r.Create(It.IsAny<CompanyEntity>()))
   .ReturnsAsync(expectedCompany);

_companyRepositoryMock
   .Setup(r => r.Create(It.IsAny<CompanyEntity>()).Result)
   .Returns(expectedCompany);

如果您不设置模拟,那么它将返回默认值。 如果您将

MockBehaviour
更改为严格,那么它将抛出异常。


更新#1

在方法

GetAllCompanies
的情况下,我必须创建一个
List<Company>()
然后返回它们?在方法
GetCompanyById
中,我必须创建一个
Company
的对象并返回它?我的意思是 xUnit 不会使用我的存储库访问数据库?

简短的回答是肯定的,你必须模拟所有你想在你的依赖上使用的方法。由于

CompanyService
正确地 依赖抽象(ICompanyRepository
 接口)而不是实现(
CompanyRepository
 类),这就是为什么您不直接依赖实体框架的原因。

如果你想测试你的存储库层/层/模块,你必须模拟

DbContext

 以避免数据库调用。有
吨的nuget包可用于减轻模拟负担。


0
投票
这是解决方案:

//Arrange var CompanyEntity = new Company(); CompanyEntity.Name = "Test Company"; CompanyEntity.Id = Guid.NewGuid(); CompanyEntity.Employees = new HashSet<Employee>(); //arrange _companyRepositoryMock .Setup(r => r.Create(It.IsAny<Company>())) .ReturnsAsync(CompanyEntity); //Act var companyCreated = await _sut.Create(CompanyEntity); //Assert Assert.NotNull(companyCreated); _companyRepositoryMock.Verify(r => r.Create(companyCreated));
    
© www.soinside.com 2019 - 2024. All rights reserved.