我正在为我的单元测试播种内存中的数据。 我可以通过UserManager添加用户,但以下调用将测试用户添加到管理员角色:
await _userManager.AddToRoleAsync(profile, "admin");
导致引发以下错误:
无法为"身份角色"创建数据库集,因为此类型不是 包含在上下文的模型中。
我可以在单元测试中通过角色管理器添加角色。 我可以将用户添加到应用程序中的角色(而不是测试(。
应用程序角色如下:
//
/// <summary>
/// Custom Application Role, inherits from IdentityRole
/// </summary>
public class ApplicationRole : IdentityRole
{
//
/// <summary>
/// No parameter constructror, let base IdentityRole handle it.
/// </summary>
public ApplicationRole() : base() { }
//
/// <summary>
/// 1 parameter constructror, let base IdentityRole handle it.
/// </summary>
/// <param name="name">just passed to base constructor</param>
public ApplicationRole(string name) : base(name) { }
//
/// <summary>
/// 2 parameter constructror, not passed to base constructor
/// </summary>
/// <param name="id"></param>
/// <param name="name"></param>
/// <remarks>Please use this constructor</remarks>
public ApplicationRole(string id, string name) : base(name)
{
this.Id = id;
}
//
public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
//
}
我的创业.cs如下所示:
public class ApplicationDbContext :
IdentityDbContext<ApplicationUser, ApplicationRole, string, IdentityUserClaim<string>, ApplicationUserRole, IdentityUserLogin<string>, IdentityRoleClaim<string>, IdentityUserToken<string>>, IDb_Context
{
private object _options;
//
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
_options = options;
}
//
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//
modelBuilder.Entity<ApplicationUser>((item) =>
{
item.Property(u => u.Id).HasMaxLength(128);
item.HasMany(u => u.UserServers).WithOne(u => u.User)
.HasForeignKey(u => u.Id).OnDelete(DeleteBehavior.Cascade);
item.HasOne(u => u.Company).WithMany(c => c.Users)
.HasForeignKey(u => u.CompanyId).OnDelete(DeleteBehavior.Restrict);
// Each User can have many UserLogins
item.HasMany(e => e.Logins).WithOne()
.HasForeignKey(ul => ul.UserId).IsRequired();
// Each User can have many UserTokens
item.HasMany(e => e.Tokens).WithOne()
.HasForeignKey(ut => ut.UserId).IsRequired();
});
//
modelBuilder.Entity<ApplicationRole>((item) =>
{
item.Property(u => u.Id).HasMaxLength(128);
item.HasKey(u => u.Id);
item.HasMany(e => e.UserRoles).WithOne(e => e.Role)
.HasForeignKey(ur => ur.RoleId).IsRequired();
});
//
modelBuilder.Entity<ApplicationUserRole>((item) =>
{
item.Property(ur => ur.UserId).HasMaxLength(128);
item.Property(ur => ur.RoleId).HasMaxLength(128);
item.HasKey(ur => new { ur.UserId, ur.RoleId });
item.HasOne(ur => ur.Role).WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.RoleId).IsRequired();
item.HasOne(ur => ur.User).WithMany(r => r.UserRoles)
.HasForeignKey(ur => ur.UserId).IsRequired();
});
//
...
}
...
//
}
我在静态帮助程序中创建上下文,如下所示:
public static ApplicationDbContext GetInMemoryApplicationDBContext()
{
ApplicationDbContext _context = null;
// Use in memory application DB context
var _optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase("db_context" + Guid.NewGuid().ToString())
.EnableSensitiveDataLogging();
_context = new ApplicationDbContext(_optionsBuilder.Options);
return _context;
}
如何让我的内存数据库将用户添加到角色?
嗯,这是一条漫长的道路,答案是我使用了以下博客文章:核心标识 ASP.NET 单元测试,源代码在GitHub上。 我使用了基本思想,但我创建了一个我继承的类,因为我使用的是 MS-Test。
using System;
using Microsoft.AspNetCore.Identity;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
//
using NSG.WebSrv;
using NSG.WebSrv.Domain.Entities;
//
namespace NSG.WebSrv_Tests
{
public class UnitTestFixture : IDisposable
{
//
static private SqliteConnection sqliteConnection;
static public ApplicationDbContext db_context;
static public UserManager<ApplicationUser> userManager;
static public RoleManager<ApplicationRole> roleManager;
//
public UnitTestFixture()
{
}
//
public void UnitTestSetup()
{
// Build service colection to create identity UserManager and RoleManager.
IServiceCollection serviceCollection = new ServiceCollection();
// Add ASP.NET Core Identity database in memory.
sqliteConnection = new SqliteConnection("DataSource=:memory:");
serviceCollection.AddDbContext<ApplicationDbContext>(
options => options.UseSqlite(sqliteConnection)
);
//
db_context = serviceCollection.BuildServiceProvider()
.GetService<ApplicationDbContext>();
db_context.Database.OpenConnection();
db_context.Database.EnsureCreated();
// Add Identity using in memory database to create UserManager and RoleManager.
serviceCollection.AddApplicationIdentity();
// Get UserManager and RoleManager.
userManager = serviceCollection.BuildServiceProvider().GetService<UserManager<ApplicationUser>>();
roleManager = serviceCollection.BuildServiceProvider().GetService<RoleManager<ApplicationRole>>();
}
//
/// <summary>
/// Cleanup resources
/// </summary>
public void Dispose()
{
if(db_context != null)
{
db_context.Database.EnsureDeleted();
db_context.Dispose();
}
sqliteConnection.Close();
}
}
}
关键是 Identity 设置为静态扩展方法,可供应用程序和测试使用:
//
/// <summary>
/// Startup Extensions
/// </summary>
public static class StartupExtensions
{
public static IServiceCollection AddApplicationIdentity(this IServiceCollection services)
{
services.AddIdentity<ApplicationUser, ApplicationRole>(
options => {
options.Stores.MaxLengthForKeys = 128;
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireLowercase = true;
options.Password.RequireUppercase = true;
options.Password.RequireNonAlphanumeric = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddUserManager<UserManager<ApplicationUser>>()
.AddRoleManager<RoleManager<ApplicationRole>>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddDefaultTokenProviders();
return services;
}
}