如何在需要 UserManager 但使用内存数据库的 XUnit 中测试方法
Posted
技术标签:
【中文标题】如何在需要 UserManager 但使用内存数据库的 XUnit 中测试方法【英文标题】:How to test method in XUnit that needs UserManager, but uses in-memory database 【发布时间】:2020-07-13 03:30:56 【问题描述】:我正在使用 ASP.NET Core 3.1 和 XUnit 进行单元测试。
我构建了一个数据库上下文工厂类,用于实例化我的数据库的内存版本:
public static class DbContextFactory
public static ApplicationDbContext CreateDbContext()
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
var modelBuilder = new ModelBuilder(new ConventionSet());
var dbContext = new ApplicationDbContext(options);
var onModelCreatingMethod = dbContext.GetType().GetMethod("OnModelCreating",
BindingFlags.Instance | BindingFlags.NonPublic);
onModelCreatingMethod.Invoke(dbContext,
new object[] modelBuilder );
return dbContext;
这是我正在尝试使用的当前测试类:
public class AdminServiceTests
public ApplicationDbContext context get; set;
public IAdminService adminService get; set;
public AdminServiceTests()
this.context = DbContextFactory.CreateDbContext();
this.adminService = new AdminService(userManager, context);
[Fact]
public async Task DeleteUserShouldDeleteUser()
// What to do ???
为了让我测试我的管理服务,我需要提供一个用户管理器。它应该与我当前创建的数据库链接。
我怎样才能做到这一点?
【问题讨论】:
你需要一个真正的用户管理器还是可以用一个模拟来代替它? 其实我不知道,我需要它像正常的一样运行,只是使用内存数据库 【参考方案1】:您在测试框架时犯了一个常见错误。您需要做的所有测试就是确保AdminService.DeleteUser
调用UserManager.DeleteAsync
。这是否会导致实际从数据库中删除用户是 1) 不是服务的问题,以及 2) ASP.NET Core Identity 和 EF Core 的实现细节,它们都有自己的广泛的测试套件来确保发生这种情况。
因此,您可以使用 Moq 之类的库来创建 UserManager<TUser>
的模拟,然后执行以下操作:
userManagerMock.Verify(x => x.DeleteAsync(user), Times.Once());
这里值得一提的是,这也有助于指出这种设计中的一些缺陷。无论您是否在其周围放置 AdminService
包装器,您都依赖于 ASP.NET Core Identity。除非您的服务在此处仅代理到UserManager
之外做了一些特殊的事情(例如协调多个操作,例如删除用户触发通知或其他东西),否则您的服务毫无意义,您应该直接使用UserManager
。开发者不断犯这种错误;为了抽象而抽象只会伤害你的代码。它增加了额外的维护问题,测试问题,并掩盖了代码实际在做什么。
【讨论】:
以上是关于如何在需要 UserManager 但使用内存数据库的 XUnit 中测试方法的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C# 页面 ASP.NET Core MVC 上使用 SignInManager 和 Usermanager
如何更改 UserManager 逻辑,以便用户在注册之前必须存在于数据库中
如何告诉 UserManager.FindByNameAsync 包含关系?
如何使用来自另一个项目 api 的 IdentityServer4 UserManager 方法
UserManager<TUser>管理用户,如何修改identity默认hash加密算法
如何在请求后使 IdentityDbContext 保持活动状态,以便服务可以使用 UserManager 完成其任务?