单元测试 IdentityDbContext
Unit Test IdentityDbContext
我读到新的 EF7 允许内存存储,这使得单元测试更容易。这在 DbContext 上效果很好,但我目前遇到的问题是我使用的是 IdentityDbContext,它没有附带该选项,或者我到目前为止还没有找到它。
我想做的是向我的 AccountController 添加单元测试,这取决于新的 UserManager 和 SignInManager 类。我想针对内存列表进行测试,但我仍然不知道如何让这些类使用不同于 EF-SQL IdentityDbContext 的 dbcontext。有什么解决办法吗?
最终,您可能希望直接模拟 UserManager
和 SignInManager
。不幸的是,beta-3 下的许多方法都不是虚拟的;你会被困在那里。但是,您可以从 UserManager and SignInManager 的来源中看出,Identity 团队似乎正在为下一个版本解决这些问题。
我个人有几个测试因为同样的问题而没有编译。
12 月2015 年 27 日 - RC1 更新
project.json
{
"version": "1.0.0-*",
"dependencies": {
"{assembly under test}": "",
"Microsoft.AspNet.Hosting": "1.0.0-*",
"xunit": "2.1.0",
"xunit.runner.dnx": "2.1.0-rc1-*"
},
"commands": {
"test": "xunit.runner.dnx"
},
"frameworks": {
"dnx451": {
"dependencies": {
"Moq": "4.2.1312.1622"
}
}
}
}
用于测试 AccountController 的测试 class 样本:
using {Your NS}.Controllers;
using Microsoft.AspNet.Identity;
using Moq;
using Xunit;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using Microsoft.Extensions.OptionsModel;
using System.Threading;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.Extensions.Logging;
namespace NS.test.Controllers
{
public class TestRole
{
public string Id { get; private set; }
public string Name { get; set; }
}
public interface ITestUserStore<T>:IUserStore<T>, IUserPasswordStore<T> where T :class
{ }
public class AccountControllerTest
{
private static UserManager<TUser> GetUserManager<TUser>(List<IUserValidator<TUser>> userValidators) where TUser : class
{
var store = new Mock<ITestUserStore<TUser>>();
store.Setup(s => s.CreateAsync(It.IsAny<TUser>(), It.IsAny<CancellationToken>())).ReturnsAsync(IdentityResult.Success);
var options = new Mock<IOptions<IdentityOptions>>();
var idOptions = new IdentityOptions();
idOptions.Lockout.AllowedForNewUsers = false;
options.Setup(o => o.Value).Returns(idOptions);
var pwdValidators = new List<PasswordValidator<TUser>>();
pwdValidators.Add(new PasswordValidator<TUser>());
var userManager = new UserManager<TUser>(store.Object, options.Object, new PasswordHasher<TUser>(),
userValidators, pwdValidators, new UpperInvariantLookupNormalizer(),
new IdentityErrorDescriber(), null,
new Mock<ILogger<UserManager<TUser>>>().Object,
null);
return userManager;
}
private static Mock<SignInManager<TUser>> MockSigninManager<TUser>(UserManager<TUser> userManager) where TUser : class
{
var context = new Mock<HttpContext>();
var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
var roleManager = new RoleManager<TestRole>(new Mock<IRoleStore<TestRole>>().Object,new RoleValidator<TestRole>[] { new RoleValidator<TestRole>() }, null, null, null, null);
var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Value).Returns(identityOptions);
var claimsFactory = new UserClaimsPrincipalFactory<TUser, TestRole>(userManager, roleManager, options.Object);
return new Mock<SignInManager<TUser>>(userManager, contextAccessor.Object, claimsFactory, options.Object, null);
}
[Fact]
public async Task RegisterTest()
{
var userValidators = new List<IUserValidator<YourUser>>();
var validator = new Mock<IUserValidator<YourUser>>();
userValidators.Add(validator.Object);
var userManager = GetUserManager(userValidators);
validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<ChatLeUser>()))
.Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
var signinManager = MockSigninManager<YourUser>(userManager);
signinManager.Setup(m => m.SignInAsync(It.IsAny<YourUser>(), It.IsAny<bool>(), null)).Returns(Task.FromResult(0)).Verifiable();
var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary());
using (var controller = new AccountController(userManager, signinManager.Object) { ViewData = viewData })
{
var result = await controller.Register(new RegisterViewModel()
{
ConfirmPassword = "test123",
Password = "Test123-123",
UserName = "test"
});
Assert.IsType<RedirectToActionResult>(result);
}
}
}
}
我读到新的 EF7 允许内存存储,这使得单元测试更容易。这在 DbContext 上效果很好,但我目前遇到的问题是我使用的是 IdentityDbContext,它没有附带该选项,或者我到目前为止还没有找到它。
我想做的是向我的 AccountController 添加单元测试,这取决于新的 UserManager 和 SignInManager 类。我想针对内存列表进行测试,但我仍然不知道如何让这些类使用不同于 EF-SQL IdentityDbContext 的 dbcontext。有什么解决办法吗?
最终,您可能希望直接模拟 UserManager
和 SignInManager
。不幸的是,beta-3 下的许多方法都不是虚拟的;你会被困在那里。但是,您可以从 UserManager and SignInManager 的来源中看出,Identity 团队似乎正在为下一个版本解决这些问题。
我个人有几个测试因为同样的问题而没有编译。
12 月2015 年 27 日 - RC1 更新
project.json
{
"version": "1.0.0-*",
"dependencies": {
"{assembly under test}": "",
"Microsoft.AspNet.Hosting": "1.0.0-*",
"xunit": "2.1.0",
"xunit.runner.dnx": "2.1.0-rc1-*"
},
"commands": {
"test": "xunit.runner.dnx"
},
"frameworks": {
"dnx451": {
"dependencies": {
"Moq": "4.2.1312.1622"
}
}
}
}
用于测试 AccountController 的测试 class 样本:
using {Your NS}.Controllers;
using Microsoft.AspNet.Identity;
using Moq;
using Xunit;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using Microsoft.Extensions.OptionsModel;
using System.Threading;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.Extensions.Logging;
namespace NS.test.Controllers
{
public class TestRole
{
public string Id { get; private set; }
public string Name { get; set; }
}
public interface ITestUserStore<T>:IUserStore<T>, IUserPasswordStore<T> where T :class
{ }
public class AccountControllerTest
{
private static UserManager<TUser> GetUserManager<TUser>(List<IUserValidator<TUser>> userValidators) where TUser : class
{
var store = new Mock<ITestUserStore<TUser>>();
store.Setup(s => s.CreateAsync(It.IsAny<TUser>(), It.IsAny<CancellationToken>())).ReturnsAsync(IdentityResult.Success);
var options = new Mock<IOptions<IdentityOptions>>();
var idOptions = new IdentityOptions();
idOptions.Lockout.AllowedForNewUsers = false;
options.Setup(o => o.Value).Returns(idOptions);
var pwdValidators = new List<PasswordValidator<TUser>>();
pwdValidators.Add(new PasswordValidator<TUser>());
var userManager = new UserManager<TUser>(store.Object, options.Object, new PasswordHasher<TUser>(),
userValidators, pwdValidators, new UpperInvariantLookupNormalizer(),
new IdentityErrorDescriber(), null,
new Mock<ILogger<UserManager<TUser>>>().Object,
null);
return userManager;
}
private static Mock<SignInManager<TUser>> MockSigninManager<TUser>(UserManager<TUser> userManager) where TUser : class
{
var context = new Mock<HttpContext>();
var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(context.Object);
var roleManager = new RoleManager<TestRole>(new Mock<IRoleStore<TestRole>>().Object,new RoleValidator<TestRole>[] { new RoleValidator<TestRole>() }, null, null, null, null);
var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Value).Returns(identityOptions);
var claimsFactory = new UserClaimsPrincipalFactory<TUser, TestRole>(userManager, roleManager, options.Object);
return new Mock<SignInManager<TUser>>(userManager, contextAccessor.Object, claimsFactory, options.Object, null);
}
[Fact]
public async Task RegisterTest()
{
var userValidators = new List<IUserValidator<YourUser>>();
var validator = new Mock<IUserValidator<YourUser>>();
userValidators.Add(validator.Object);
var userManager = GetUserManager(userValidators);
validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<ChatLeUser>()))
.Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
var signinManager = MockSigninManager<YourUser>(userManager);
signinManager.Setup(m => m.SignInAsync(It.IsAny<YourUser>(), It.IsAny<bool>(), null)).Returns(Task.FromResult(0)).Verifiable();
var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary());
using (var controller = new AccountController(userManager, signinManager.Object) { ViewData = viewData })
{
var result = await controller.Register(new RegisterViewModel()
{
ConfirmPassword = "test123",
Password = "Test123-123",
UserName = "test"
});
Assert.IsType<RedirectToActionResult>(result);
}
}
}
}