Net Core:如何使用数据库行简化单元测试存储库和服务

时间:2019-07-30 23:07:26

标签: c# asp.net-core .net-core moq xunit

我在实体框架中有一个模型。我想确保应用程序服务正在读取正确指向数据库的通用存储库。我有点被困在Xunit中如何测试呢?收到以下错误,也许我需要重写代码。需要验证App服务可以读取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?)  

程序中也有依赖项注入。打开以根据需要重写的代码,

1 个答案:

答案 0 :(得分:0)

您不想创建DepartmentAppService的模拟。您要创建一个实例。您要测试的方法需要真实对象的实例,而不是模拟对象。您想测试实际对象的代码,模拟不运行任何代码,而仅返回伪数据。

        var config = new MapperConfiguration(cfg =>
        {
            cfg.AddProfile(sharedServicesProfile);
        });
        mapper = config.CreateMapper();

var departmentAppService = new DepartmentAppService(departmentRepositoryMock.Object, mapperMock.Object);

如果您使用的是InMemory数据库,并且实际上是从该InMemory数据库获取存储库的数据,则您也不想模拟存储库,因为您正在访问物理数据库并返回真实数据而不是模拟数据

说实话,我认为您需要阅读更多有关测试和模拟的信息。似乎缺少了一些核心概念...这是一种编写您尝试做的事情的方法。

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);

您可能还想考虑布置上下文或将其包装在使用中。如果复制粘贴后代码无法正确运行,则可能需要进行一些调整,但应该相当接近。

从上面的代码中可以看到,您仍然需要学习何时模拟和何时不模拟!不需要模拟。您也正在进行集成测试,如果您不想进行集成测试,则可以删除上下文内容并模拟存储库,并设置模拟以返回部门。