【问题标题】:Mocked UserManager and roleManager methods are returning null模拟的 UserManager 和 roleManager 方法返回 null
【发布时间】:2019-07-27 08:12:02
【问题描述】:

我已经模拟了 userManager 并使用返回值设置了所需的函数。

但是,每当我尝试运行单元测试时,即使我设置的返回值不同,我也会不断收到错误/失败的返回值。

    [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() 应该被模拟对象替换,并且应该返回我们配置模拟对象返回的任何内容。

我做错了什么?

谢谢:)

【问题讨论】:

    标签: asp.net unit-testing asp.net-core moq nunit-3.0


    【解决方案1】:

    问题在于您的模拟设置。如果您使用特定对象或值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.FindByEmailAsync() 返回 null 这可能是问题所在;但不管我传递给 RoleStore 方法的参数是什么;它不应该给我我指示它给的嘲笑回报吗?
    • @AbhilashGopalakrishna moq 尝试将调用与设置匹配,但在您的情况下,设置具有新实例,该实例始终与实际调用中的实例不同。我更新了答案,又发现了一个问题。
    • 那是个愚蠢的错误;谢谢:) 在尝试了您的建议后,我已经更新了新代码。我仍然得到相同的 false 返回值。这可能是我犯的另一个调用错误。您可以在编辑中看到任何明显的错误吗?非常感谢:)
    • @AbhilashGopalakrishna .ReturnsAsync(It.Is&lt;IdentityUser&gt;(u =&gt; u.UserName == email)); 这是错误的,因为它实际上会返回 null :),将其恢复为以前的实现...
    • 您好,谢谢:) 解决了空用户问题;我犯了一个严重的错误。:) 我正在使用 userManager.IsInRoleAsync 但正在模拟角色存储中的 IsInRoleAsync。我还没有看到用户管理器如何调用 IsInRoleAsync。但这似乎解决了问题;谢谢:)
    猜你喜欢
    • 2011-09-30
    • 1970-01-01
    • 2020-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多