如何对不使用存储库的处理程序进行单元测试?

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

假设我有一个以这种方式实现的处理程序。没有存储库,逻辑按以下方式编写在处理程序内部。

既然我不应该嘲笑 EF,那么一个单元将如何测试它,因为它确实包含逻辑。

示例 - 我缩短了代码:

public record GetUsersQuery : IRequest<UserResult>
{
    public List<string> UserType { get; set; }
}

internal sealed class GetUsersQueryHandler : IRequestHandler<GetUsersQuery, UserResult>
{
    private readonly IDbContext context;

    public GetUsersQueryHandler(IDbContext context)
    {
        this.context = context;
    }

    public async Task<UserResult> Handle(GetUsersQuery query, CancellationToken cancellationToken)
    {
        var baseQuery = context.AppUsers.AsQueryable();

        baseQuery = baseQuery.Where(user => query.UserType.Contains(user.UserType));

        /*
            More Logic
        */

        result = await baseQuery.ToListAsync(cancellationToken);

        return MapToUserResult(result);
    }
}
c# .net entity-framework unit-testing moq
1个回答
0
投票

测试这一点很困难,但并非不可能。我可以想到两个选择。

改为编写集成测试

如果您无法按原样更改代码,您可以考虑编写测试,以便代码也使用数据库。有些人会将此称为集成测试而不是单元测试,但如果做得正确,您仍然可以对代码进行自动测试覆盖。

关键是要做得正确,因为数据库是持久的。因此,您不能依赖垃圾收集在每次测试后进行清理。相反,您必须明确确保每个测试不会留下影响下一个测试的状态。

此外,您可能还需要在每次测试运行之前自动配置数据库。这些都不是不可能的,但另一方面也不是微不足道的,并且往往会使测试变慢。虽然我确实使用这种技术,但我倾向于考虑测试金字塔:不要过度。

有很多不同的方法可以做到这一点,即使在 .NET 上也是如此。我在我的书

适合你头脑的代码中描述了一种这样的方式。

应用依赖倒置原则

您可以将实体框架视为一个实现细节。我愿意。

根据

依赖倒置原则,客户端代码应该依赖于抽象而不是实现细节。客户端代码应该定义抽象应该是什么样子,而不是通过抽象泄漏实现细节。

在这种情况下,看起来

GetUsersQueryHandler

真的需要一种方法来查询存储库以获取用户(?)

因此,定义一个执行此操作的接口,并将其注入到

GetUsersQueryHandler

 而不是 
IDbContext
 中。将 
IDbContext
Where
 子句等移至新接口的实现中。

© www.soinside.com 2019 - 2024. All rights reserved.