在测试中创建 UserManager<T> 实例
Creating an instance of UserManager<T> in tests
我对模拟的概念很陌生,我在 injecting/mocking 和 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 : Store does not implement IUserPasswordStore.
如何在测试中创建工作 UserManager<T>
实例?
我正在使用 Xunit
首先修改你的方法,我读过一些不同的论文,人们说你不需要测试已经测试过的库和工具。
但有时我们需要模拟 UserManager
来注入我们的服务并解决这些依赖关系。
UserManager
可以模拟得非常简单,但是像这样的错误信息并没有得到很好的解释。
我们必须首先模拟 UserStore
并将其提供给 UserManager
,要模拟 UserStore,您可以创建一个 class MockUserStore
派生 IUserStore
和 IUserPasswordStore
:
public class MockUserStore : IUserStore<TUser>, IUserPasswordStore<TUser>
这个 mock class 必须实现 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));
}
您还可以使用 class 来模拟 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);
}
}
毕竟你可以通过模拟 UserStore
:
来模拟 UserManager
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;
我对模拟的概念很陌生,我在 injecting/mocking 和 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 : Store does not implement IUserPasswordStore.
如何在测试中创建工作 UserManager<T>
实例?
我正在使用 Xunit
首先修改你的方法,我读过一些不同的论文,人们说你不需要测试已经测试过的库和工具。
但有时我们需要模拟 UserManager
来注入我们的服务并解决这些依赖关系。
UserManager
可以模拟得非常简单,但是像这样的错误信息并没有得到很好的解释。
我们必须首先模拟 UserStore
并将其提供给 UserManager
,要模拟 UserStore,您可以创建一个 class MockUserStore
派生 IUserStore
和 IUserPasswordStore
:
public class MockUserStore : IUserStore<TUser>, IUserPasswordStore<TUser>
这个 mock class 必须实现 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));
}
您还可以使用 class 来模拟 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);
}
}
毕竟你可以通过模拟 UserStore
:
UserManager
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;