c# - 依赖注入 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);
解决方案
如果您在 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
类。
推荐阅读
- rest - 如何知道哪个 fareComponent 与 BargainFinderMaxRS 中的段相关联
- mysql - WITH (...) IF ... IN ... 在 MySQL 触发器中
- python - 编写一个名为 index_of_smallest 的函数,它接受一个整数列表
- c++ - 我们如何使用下面的集合构造函数示例构造集合元素?
- r - 将 S4 对象转换为数据框 (R) 的一般方法
- ios - 如何正确设置 RN AccessibilityInfo setAccessibilityFocus
- javascript - 用javascript/html分隔男性和女性名字?
- excel - 如何编写自定义格式以使 3.33 显示为“3.33”但 3 显示为“3”?
- git - 具有两个分支的存储库与远程不同,如何修复?
- sql - 为不同时间段的数据计算条形图的最佳方法是什么