首页 > 解决方案 > 依赖注入 ASP.NET 身份用户(和单元测试)

问题描述

我不完全了解如何重构我的应用程序以使其更具可测试性。

我正在使用 ASP.NET Core 3.0(Razor Pages,如果重要的话)。

当前状态:

我有在我的上下文中注入的剃须刀页面模型(继承自 IdentityDbContext)和 userManager:

public class DashboardModel : PageModel
{

    private readonly ApplicationDbContext _context;
    private readonly UserManager<AVUser> _userManager;

    public DashboardModel(ApplicationDbContext context, UserManager<AVUser> userManager)
    {
        _context = context;
        _userManager = userManager;
    }
    public async Task<IActionResult> OnGetAsync()
    {
        AVUser = await _userManager.GetUserAsync(User);
        MyRepository myRepository = new MyRepository(_context, AVUser);

        // omitted - just getting data from the repository for use on the page

        return Page();
    }

我创建了具有以下构造函数的存储库:

public MyRepository(ApplicationDbContext context, AVUser user) 

我从不直接在我的模型类中使用上下文,而是使用传入的上下文在模型类中创建存储库。在这种情况下,ApplicationDbContext 是我的 EF Core 上下文,而 AVUser 是我的身份用户类型,定义为:

public class AVUser : IdentityUser

我的 DI 设置为:

// DB Setup
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));


// Identity Setup
        services.AddDefaultIdentity<AVUser>(config =>
        {
            config.SignIn.RequireConfirmedEmail = true; 
        })
        .AddEntityFrameworkStores<ApplicationDbContext>();

我不明白的

我想让我的剃须刀页面模型类可单元测试,而不依赖于数据库或存储库类,模拟存储库类,所以我希望我必须从构造函数中删除上下文,而是为我的存储库和 DI 创建接口。

但是,我不知道如何在存储库的用户参数中进行 DI - 如何在 Startup.cs 中设置我的服务以便可以传入?今天为了得到这个值,我运行:

AVUser = await _userManager.GetUserAsync(User);

标签: c#dependency-injectionasp.net-identityrazor-pages

解决方案


如果您在 DI 容器中注入存储库,IoC 将自动注入它们的依赖项,例如控制器和页面。所以你只需要在你的存储库类中有一个这样的构造函数:

private readonly ApplicationDbContext _context;
private readonly UserManager<AVUser> _userManager;

public MyRepository(ApplicationDbContext context, UserManager<AVUser> userManager)
{
    _context = context;
    _userManager = userManager;
}

然后将其注入容器:

services.AddTransient<IMyRepository,MyRepository>();

就是这样。请记住为您的存储库创建一个接口,以便您可以为生产或测试注入不同的实例。尽管如此,您不应该依赖 DI 进行测试。如果您正在编写单元测试,那么为您的 MyRepository 创建一个测试实现并简单地实例化它。如果您正在编写集成测试,那么您必须使用不同的sturtup类。


推荐阅读