【问题标题】:How to structure a service that needs multiple repositories?如何构建需要多个存储库的服务?
【发布时间】:2017-04-12 13:04:24
【问题描述】:

我有一个使用 2 个存储库的服务,我想进行单元测试。因此,为了测试,我需要让构造函数直接采用接口而不是存储库类,这样我就可以模拟存储库。但是我不能将他们的 DbContext 设置为相同,这会导致其他问题。

代码如下:

public class RolePrivilegeService : IRolePrivilegeService
{
    private readonly RoleReadWriteRepository _roleRepo;
    private readonly PrivilegeReadRepository _privilegeRead;

    public RolePrivilegeService(RoleReadWriteRepository roleWrite, 
        PrivilegeReadRepository privilegeRead)
    {
        _roleRepo = roleWrite;
        _privilegeRead = privilegeRead;

        _roleRepo.Db = _privilegeRead.Db;
    }

    public async Task<int> AssignPrivilege(string roleId, string privilegeId, string companyId)
    {
        var role = await _roleRepo.FindRole(companyId, roleId);
        if(role == null) throw new RoleNotFoundException();

        var privilege = await _privilegeRead.Find(privilegeId);
        if(privilege == null) throw new PrivilegeNotFoundException();

        role.AssignPrivilege(privilege);

        return await _roleRepo.UpdateRole(role);
    }
}

接口和实体在一个项目中,服务和存储库在另一个项目中。

【问题讨论】:

  • 通过抽象出实现关注点以便可以模拟它们。类应该依赖于抽象而不是具体。
  • 我不明白为什么注入存储库接口会禁止模拟 DbContext。我猜您的存储库也使用构造函数注入。如果是这样,当然没有理由反对模拟 Entity Framework DbContext - 只需在创建存储库之前创建适当的实例。

标签: entity-framework unit-testing mocking repository-pattern


【解决方案1】:

我想从一开始就让服务负责管理上下文的唯一性并不是最佳解决方案。

一些可能的解决方案(我最喜欢的是第三个)

1) 改用接口并注入 DBContext(在此处定义您的策略,如果您使用 api 或其他方式,请根据请求创建一个 DBContext...)

2) 你无论如何都可以用 NSubstitute 或其他人模拟一个具体的类

3) 通过拥有一个存储库来改进您的设计,以更好地抽象所需的实体(使用聚合来更好地抽象事务边界)

【讨论】:

    猜你喜欢
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 2019-09-11
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    • 2020-03-05
    相关资源
    最近更新 更多