模拟的 UserManager 和 roleManager 方法返回 null
Mocked UserManager and roleManager methods are returning null
我模拟了 userManager 并使用 return 值设置了所需的函数。
然而,每当我尝试 运行 单元测试时,我总是得到 false/failed return 值,即使我设置的 return 值不同。
[TestCase]
public async Task Verify_UserInRole_False()
{
var userRole = "Supervisor";
var email = "test@test.com";
var mockUserStore = new Mock<IUserStore<IdentityUser>>();
var mockUserRoleStore = mockUserStore.As<IUserRoleStore<IdentityUser>>();
var mockedUserManager = new Mock<UserManager<IdentityUser>>(new Mock<IUserStore<IdentityUser>>(mockUserRoleStore).Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<IPasswordHasher<IdentityUser>>().Object,
new IUserValidator<IdentityUser>[0],
new IPasswordValidator<IdentityUser>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<IServiceProvider>().Object,
new Mock<ILogger<UserManager<IdentityUser>>>().Object);
mockedUserManager.Setup(x => x.FindByEmailAsync(email))
.ReturnsAsync(It.Is<IdentityUser>(u => u.UserName == email));
mockUserRoleStore.Setup(x => x.IsInRoleAsync(It.Is<IdentityUser>(u => u.UserName == email), userRole, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
AdminController adminController = new AdminController(hostingEnvironment, signInManager, logger, roleManager, mockedUserManager.Object);
var actionResult = await adminController.CheckIfUserIsInRole(email, userRole);
Assert.IsTrue(actionResult);
}
待测方法:
public async Task<bool> CheckIfUserIsInRole(string email, string role)
{
return await _userManager.IsInRoleAsync(await _userManager.FindByEmailAsync(email), role);
}
userManager 的各种方法如 AddToRole() 也是如此;等等
据我了解:
当我嘲笑 IsInRoleAsync() 时,
一旦 CheckIfUserIsInRole(...) 方法被命中,
IsInRoleAsync() 应该替换为模拟对象,并且应该 return 无论我们将模拟对象配置为 return.
我做错了什么?
谢谢:)
问题出在您的模拟设置上。如果您使用特定对象或值 moq
将使用 IEquatable.Equals
比较实例。您有以下设置:
mockedUserManager.Setup(x => x.FindByEmailAsync(email))
.ReturnsAsync(new IdentityUser { UserName = email });
mockUserRoleStore.Setup(x => x.IsInRoleAsync(new IdentityUser() { UserName = email }, userRole, ct))
.ReturnsAsync(true);
由于您每次都创建新实例,因此您的设置从未真正匹配过。考虑将第二个设置更改为:
mockUserRoleStore.Setup(x => x.IsInRoleAsync(It.IsAny<IdentityUser>(), userRole, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
或更具体地说
mockUserRoleStore.Setup(x => x.IsInRoleAsync(It.Is<IdentityUser>(u => u.UserName == email), userRole, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
更新
我注意到另一个问题,因为您没有使用模拟的 mockUserRoleStore
而是使用新的模拟实例初始化 mockedUserManager
:
var mockUserRoleStore = mockUserStore.As<IUserRoleStore<IdentityUser>>();
var mockedUserManager = new Mock<UserManager<IdentityUser>>(mockUserRoleStore.Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<IPasswordHasher<IdentityUser>>().Object,
new IUserValidator<IdentityUser>[0],
new IPasswordValidator<IdentityUser>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<IServiceProvider>().Object,
new Mock<ILogger<UserManager<IdentityUser>>>().Object);
我模拟了 userManager 并使用 return 值设置了所需的函数。
然而,每当我尝试 运行 单元测试时,我总是得到 false/failed return 值,即使我设置的 return 值不同。
[TestCase]
public async Task Verify_UserInRole_False()
{
var userRole = "Supervisor";
var email = "test@test.com";
var mockUserStore = new Mock<IUserStore<IdentityUser>>();
var mockUserRoleStore = mockUserStore.As<IUserRoleStore<IdentityUser>>();
var mockedUserManager = new Mock<UserManager<IdentityUser>>(new Mock<IUserStore<IdentityUser>>(mockUserRoleStore).Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<IPasswordHasher<IdentityUser>>().Object,
new IUserValidator<IdentityUser>[0],
new IPasswordValidator<IdentityUser>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<IServiceProvider>().Object,
new Mock<ILogger<UserManager<IdentityUser>>>().Object);
mockedUserManager.Setup(x => x.FindByEmailAsync(email))
.ReturnsAsync(It.Is<IdentityUser>(u => u.UserName == email));
mockUserRoleStore.Setup(x => x.IsInRoleAsync(It.Is<IdentityUser>(u => u.UserName == email), userRole, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
AdminController adminController = new AdminController(hostingEnvironment, signInManager, logger, roleManager, mockedUserManager.Object);
var actionResult = await adminController.CheckIfUserIsInRole(email, userRole);
Assert.IsTrue(actionResult);
}
待测方法:
public async Task<bool> CheckIfUserIsInRole(string email, string role)
{
return await _userManager.IsInRoleAsync(await _userManager.FindByEmailAsync(email), role);
}
userManager 的各种方法如 AddToRole() 也是如此;等等
据我了解: 当我嘲笑 IsInRoleAsync() 时, 一旦 CheckIfUserIsInRole(...) 方法被命中, IsInRoleAsync() 应该替换为模拟对象,并且应该 return 无论我们将模拟对象配置为 return.
我做错了什么?
谢谢:)
问题出在您的模拟设置上。如果您使用特定对象或值 moq
将使用 IEquatable.Equals
比较实例。您有以下设置:
mockedUserManager.Setup(x => x.FindByEmailAsync(email))
.ReturnsAsync(new IdentityUser { UserName = email });
mockUserRoleStore.Setup(x => x.IsInRoleAsync(new IdentityUser() { UserName = email }, userRole, ct))
.ReturnsAsync(true);
由于您每次都创建新实例,因此您的设置从未真正匹配过。考虑将第二个设置更改为:
mockUserRoleStore.Setup(x => x.IsInRoleAsync(It.IsAny<IdentityUser>(), userRole, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
或更具体地说
mockUserRoleStore.Setup(x => x.IsInRoleAsync(It.Is<IdentityUser>(u => u.UserName == email), userRole, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
更新
我注意到另一个问题,因为您没有使用模拟的 mockUserRoleStore
而是使用新的模拟实例初始化 mockedUserManager
:
var mockUserRoleStore = mockUserStore.As<IUserRoleStore<IdentityUser>>();
var mockedUserManager = new Mock<UserManager<IdentityUser>>(mockUserRoleStore.Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<IPasswordHasher<IdentityUser>>().Object,
new IUserValidator<IdentityUser>[0],
new IPasswordValidator<IdentityUser>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<IServiceProvider>().Object,
new Mock<ILogger<UserManager<IdentityUser>>>().Object);