我对模拟的概念还很陌生,并且在向测试中注入/模拟UserManager<T>
时感到很困难
我需要使用await _userManager.CreateAsync(user, password);
我找到了这个
public static UserManager<TUser> TestUserManager<TUser>(IUserStore<TUser> store = null) where TUser : class
{
store = store ?? new Mock<IUserStore<TUser>>().Object;
var options = new Mock<IOptions<IdentityOptions>>();
var idOptions = new IdentityOptions();
idOptions.Lockout.AllowedForNewUsers = false;
options.Setup(o => o.Value).Returns(idOptions);
var userValidators = new List<IUserValidator<TUser>>();
var validator = new Mock<IUserValidator<TUser>>();
userValidators.Add(validator.Object);
var pwdValidators = new List<PasswordValidator<TUser>>();
pwdValidators.Add(new PasswordValidator<TUser>());
var userManager = new UserManager<TUser>(store, options.Object, new PasswordHasher<TUser>(),
userValidators, pwdValidators, new UpperInvariantLookupNormalizer(),
new IdentityErrorDescriber(), null,
new Mock<ILogger<UserManager<TUser>>>().Object);
validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<TUser>()))
.Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
return userManager;
}
但这会引发
System.NotSupportedException:存储未实现IUserPasswordStore。
如何在测试中创建有效的UserManager<T>
实例?
我正在使用Xunit
答案 0 :(得分:1)
首先,对您的方法进行修订,我读了一些不同的文章,人们说您不需要测试库和已经测试过的工具。
但是有时我们需要模拟UserManager
来注入我们的服务并解决这些依赖关系。
UserManager
的模拟非常简单,但是并没有很好地解释类似的错误消息。
我们必须首先模拟UserStore
并将其提供给UserManager
,要模拟UserStore,您可以创建派生MockUserStore
和IUserStore
的类IUserPasswordStore
:
public class MockUserStore : IUserStore<TUser>, IUserPasswordStore<TUser>
该模拟类必须实现IUserPasswordStore的某些方法,否则您将捕获该错误消息!
public Task SetPasswordHashAsync(TUser user, string passwordHash,
CancellationToken cancellationToken)
{
user.PasswordHash = passwordHash;
return Task.FromResult(0);
}
public Task<string> GetPasswordHashAsync(TUser user, CancellationToken cancellationToken)
{
return Task.FromResult<string>(user.PasswordHash);
}
public Task<bool> HasPasswordAsync(TUser user, CancellationToken cancellationToken)
{
return Task.FromResult<bool>(!String.IsNullOrEmpty(user.PasswordHash));
}
您还可以使用类来模拟UserManager
并使用模拟方法覆盖其方法:
public class MockUserManager : UserManager<TUser>
{
public MockUserManager(IUserStore<TUser> store, IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<TUser> passwordHasher, IEnumerable<IUserValidator<TUser>> userValidators,
IEnumerable<IPasswordValidator<TUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<TUser>> logger)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
}
public override Task<IdentityResult> CreateAsync(TUser user)
{
return Task.FromResult(IdentityResult.Success);
}
}
毕竟,您可以通过传递模拟的UserManager
来模拟UserStore
:
var userStore = new MockUserStore();
var userManager = new MockUserManager(userStore,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<IPasswordHasher<AppUser>>().Object,
new IUserValidator<TUser>[0],
new IPasswordValidator<TUser>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<IServiceProvider>().Object,
new Mock<ILogger<UserManager<TUser>>>().Object);
return userManager;