Net Core:如何使用数据库行对存储库和服务进行简单单元测试
Net Core: How to Simple Unit Test Repository and Service with Database Rows
我在 Entity Framework 有一个模型。我想确保应用程序服务正在正确读取指向数据库的通用存储库。我如何在 Xunit 中测试它,我有点卡住了?收到以下错误,也许我需要重写代码。需要验证应用服务可以读取 InMemory 数据库中下面的示例数据行。
型号:
public partial class Department
{
public int DepartmentId { get; set; }
public string DepartmentCode { get; set; }
public string DepartmentName { get; set; }
.... plus additional
}
DTO:
public class DepartmentDto
{
public int DepartmentId { get; set; }
public string DepartmentCode { get; set; }
public string DepartmentName { get; set; }
}
来自 IRepository 的基本存储库:
public async Task<T> GetAsync(int id)
{
return await Table.FindAsync(id);
}
**Constructor:**
public BaseRepository(DbContext context)
{
_context = context;
Table = _context.Set<T>();
}
服务:DepartmentAppService.cs
public async Task<DepartmentDto> GetDepartmentById(int id)
{
var department = await departmentRepository.GetAsync(id);
var departmentDto = mapper.Map<Department, DepartmentDto>(department);
return departmentDto;
}
**Constructor:**
public DepartmentAppService(IRepository<Department> departmentRepository, IMapper mapper)
{
this.departmentRepository = departmentRepository;
this.mapper = mapper;
}
尝试的测试代码:
public async Task Get_DepartmentById_Are_Equal()
{
var options = new DbContextOptionsBuilder<TestContext>()
.UseInMemoryDatabase(databaseName: "TestDatabase")
.Options;
var context = new TestContext(options);
Mock<IRepository<Department>> departmentRepositoryMock = new Mock<IRepository<Department>>();
Mock<IMapper> mapperMock = new Mock<IMapper>();
Mock<DepartmentAppService> departmentAppServiceMock = new Mock<DepartmentAppService>(departmentRepositoryMock, mapperMock);
context.Department.Add(new Department { DepartmentId = 2, DepartmentCode = "123", DepartmentName = "ABC" });
var test = await departmentAppServiceMock.GetDepartmentById(5);
Assert.Equal("123", test.DepartmentCode);
接收错误:如何修复?
'Mock<DepartmentAppService>' does not contain a definition for 'GetDepartmentById' and no accessible extension method 'GetDepartmentById' accepting a first argument of type 'Mock<DepartmentAppService>' could be found (are you missing a using directive or an assembly reference?)
程序中也有依赖注入。对根据需要重写的代码开放,
您不想创建 DepartmentAppService
的模拟。你想创建一个实例。您正在测试的方法需要真实对象的实例,而不是模拟对象。您想测试实际对象的代码,模拟不会 运行 任何代码,而只会 return 假数据。
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(sharedServicesProfile);
});
mapper = config.CreateMapper();
var departmentAppService = new DepartmentAppService(departmentRepositoryMock.Object, mapperMock.Object);
如果您使用的是 InMemory 数据库,并且您实际上是从该 InMemory 数据库获取存储库的数据,则您不希望在访问物理数据库时模拟您的存储库,并且 return正在处理真实数据而不是模拟数据。
老实说,我认为您需要阅读更多有关测试和模拟的内容。看起来缺少一些核心概念......这是一种编写你想要做的事情的方法。
AutoMapper.Mapper.Initialize(m => m.AddProfile<YOUR AUTOMAPPER PROFILE>());
AutoMapper.Mapper.AssertConfigurationIsValid();
var options = new DbContextOptionsBuilder<TestContext>()
.UseInMemoryDatabase(databaseName: "TestDatabase")
.Options;
var context = new TestContext(options))
context.Department.Add(new Department { DepartmentId = 2, DepartmentCode = "123", DepartmentName = "ABC" });
context.SaveChanges();
var departmentRepository = new Repository<Department>>(context);
var departmentAppService = new DepartmentAppService(departmentRepository, mapper);
var test = await departmentAppService.GetDepartmentById(5);
Assert.Equal("123", test.DepartmentCode);
您可能还想考虑处置上下文或将其包装在 using 中。如果代码不正确 运行 如果您复制粘贴,则可能需要进行一些调整,但应该相当接近。
正如您从上面的代码中看到的,您仍然需要学习何时进行模拟,何时不进行模拟!不需要模拟。您还在进行集成测试,如果您不想进行集成测试,您可以删除上下文内容并模拟存储库并将模拟设置为 return 部门。
我在 Entity Framework 有一个模型。我想确保应用程序服务正在正确读取指向数据库的通用存储库。我如何在 Xunit 中测试它,我有点卡住了?收到以下错误,也许我需要重写代码。需要验证应用服务可以读取 InMemory 数据库中下面的示例数据行。
型号:
public partial class Department
{
public int DepartmentId { get; set; }
public string DepartmentCode { get; set; }
public string DepartmentName { get; set; }
.... plus additional
}
DTO:
public class DepartmentDto
{
public int DepartmentId { get; set; }
public string DepartmentCode { get; set; }
public string DepartmentName { get; set; }
}
来自 IRepository 的基本存储库:
public async Task<T> GetAsync(int id)
{
return await Table.FindAsync(id);
}
**Constructor:**
public BaseRepository(DbContext context)
{
_context = context;
Table = _context.Set<T>();
}
服务:DepartmentAppService.cs
public async Task<DepartmentDto> GetDepartmentById(int id)
{
var department = await departmentRepository.GetAsync(id);
var departmentDto = mapper.Map<Department, DepartmentDto>(department);
return departmentDto;
}
**Constructor:**
public DepartmentAppService(IRepository<Department> departmentRepository, IMapper mapper)
{
this.departmentRepository = departmentRepository;
this.mapper = mapper;
}
尝试的测试代码:
public async Task Get_DepartmentById_Are_Equal()
{
var options = new DbContextOptionsBuilder<TestContext>()
.UseInMemoryDatabase(databaseName: "TestDatabase")
.Options;
var context = new TestContext(options);
Mock<IRepository<Department>> departmentRepositoryMock = new Mock<IRepository<Department>>();
Mock<IMapper> mapperMock = new Mock<IMapper>();
Mock<DepartmentAppService> departmentAppServiceMock = new Mock<DepartmentAppService>(departmentRepositoryMock, mapperMock);
context.Department.Add(new Department { DepartmentId = 2, DepartmentCode = "123", DepartmentName = "ABC" });
var test = await departmentAppServiceMock.GetDepartmentById(5);
Assert.Equal("123", test.DepartmentCode);
接收错误:如何修复?
'Mock<DepartmentAppService>' does not contain a definition for 'GetDepartmentById' and no accessible extension method 'GetDepartmentById' accepting a first argument of type 'Mock<DepartmentAppService>' could be found (are you missing a using directive or an assembly reference?)
程序中也有依赖注入。对根据需要重写的代码开放,
您不想创建 DepartmentAppService
的模拟。你想创建一个实例。您正在测试的方法需要真实对象的实例,而不是模拟对象。您想测试实际对象的代码,模拟不会 运行 任何代码,而只会 return 假数据。
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(sharedServicesProfile);
});
mapper = config.CreateMapper();
var departmentAppService = new DepartmentAppService(departmentRepositoryMock.Object, mapperMock.Object);
如果您使用的是 InMemory 数据库,并且您实际上是从该 InMemory 数据库获取存储库的数据,则您不希望在访问物理数据库时模拟您的存储库,并且 return正在处理真实数据而不是模拟数据。
老实说,我认为您需要阅读更多有关测试和模拟的内容。看起来缺少一些核心概念......这是一种编写你想要做的事情的方法。
AutoMapper.Mapper.Initialize(m => m.AddProfile<YOUR AUTOMAPPER PROFILE>());
AutoMapper.Mapper.AssertConfigurationIsValid();
var options = new DbContextOptionsBuilder<TestContext>()
.UseInMemoryDatabase(databaseName: "TestDatabase")
.Options;
var context = new TestContext(options))
context.Department.Add(new Department { DepartmentId = 2, DepartmentCode = "123", DepartmentName = "ABC" });
context.SaveChanges();
var departmentRepository = new Repository<Department>>(context);
var departmentAppService = new DepartmentAppService(departmentRepository, mapper);
var test = await departmentAppService.GetDepartmentById(5);
Assert.Equal("123", test.DepartmentCode);
您可能还想考虑处置上下文或将其包装在 using 中。如果代码不正确 运行 如果您复制粘贴,则可能需要进行一些调整,但应该相当接近。
正如您从上面的代码中看到的,您仍然需要学习何时进行模拟,何时不进行模拟!不需要模拟。您还在进行集成测试,如果您不想进行集成测试,您可以删除上下文内容并模拟存储库并将模拟设置为 return 部门。