我正在尝试使用 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。 任何可能的解决方案?提前致谢。
你只是忘了在 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
的对象并返回它?我的意思是 xUnit 不会使用我的存储库访问数据库?Company
简短的回答是肯定的,你必须模拟所有你想在你的依赖上使用的方法。由于
CompanyService
正确地 依赖抽象(ICompanyRepository
接口)而不是实现(
CompanyRepository
类),这就是为什么您不直接依赖实体框架的原因。如果你想测试你的存储库层/层/模块,你必须模拟
DbContext
以避免数据库调用。有吨的nuget包可用于减轻模拟负担。
//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));