C# 注入ASP.NET身份用户的依赖项(和单元测试)

C# 注入ASP.NET身份用户的依赖项(和单元测试),c#,dependency-injection,asp.net-identity,razor-pages,C#,Dependency Injection,Asp.net Identity,Razor Pages,我不完全理解如何重构我的应用程序,使其更易于测试 我使用的是ASP.NETCore3.0(剃须刀页面,如果需要的话) 当前状态: 我有razor pages模型,可以在我的上下文(继承自IdentityDbContext)和userManager中注入: public class DashboardModel : PageModel { private readonly ApplicationDbContext _context; private readonly UserMa

我不完全理解如何重构我的应用程序,使其更易于测试

我使用的是ASP.NETCore3.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();
    }
我从不在模型类中直接使用上下文,而是使用传入的上下文在模型类中创建存储库。在本例中,ApplicationDbContext是我的EF核心上下文,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容器,IoC将自动注入它们的依赖项,如控制器和页面。因此,您只需要在存储库类中有这样一个构造函数:

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

public MyRepository(ApplicationDbContext context, UserManager<AVUser> userManager)
{
    _context = context;
    _userManager = userManager;
}
private readonly ApplicationDbContext\u上下文;
私有只读用户管理器_UserManager;
公共MyRepository(ApplicationDbContext上下文,UserManager UserManager)
{
_上下文=上下文;
_userManager=userManager;
}
然后将其注入容器:

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

公共仪表板模型(ApplicationDbContext,UserManager UserManager)是什么样子?当你说Razorpage的模型时,这是否意味着当你的控制器返回该视图时,它就是传递进来的对象?例如
返回视图(“View.cshtml”,dashBoardModelObject)
?我扩展了我的问题,在这里包含了更多的代码。它只是一个razor page.html.cs文件,用于从存储库中获取页面的一些数据。谢谢,我遵循这一点,但有一个问题-在本例中,我现在将UserManager注入到Repo中,而不是AVUser对象本身。我在想,我希望将AVUser传递到存储库,这样,如果我在ASP.NET上下文之外利用我的存储库(例如,在控制台应用程序中生成演示数据),我可以在控制台应用程序中创建一个AVUser对象并将其传递,并且repo类不必在ASP.NET上下文中运行。这有意义吗?而且在依赖DI进行测试这一点上也很公平——只要我转换到接口,DI对此并不重要,我仍然可以通过拥有测试对象来编写测试!从技术上讲,您不应该有任何问题,但是,您可以解决这个问题,只需在DI容器中注册一个AVUser,它在构造函数中接受UserManager,然后将AVUser注入存储库。无论哪种情况,你都很好。
private readonly ApplicationDbContext _context;
private readonly UserManager<AVUser> _userManager;

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