模拟的 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);