模拟的UserManager和roleManager方法返回null

时间:2019-03-05 19:12:32

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

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

我在做什么错了?

谢谢:)

1 个答案:

答案 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);

更新

我注意到了另一个问题,因为您不是使用模拟的mockedUserManager而是使用新的模拟实例来初始化mockUserRoleStore

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);