如何模拟Asp.net身份UserManager的CreateAsync方法

时间:2015-02-21 11:28:42

标签: c# asp.net moq

我正在尝试模拟UserStore的CreateAsync方法以拥有内存中的用户存储。

public void Can_Create_User()
{
    //Arrange
    var dummyUser = new ApplicationUser() { UserName = "PinkWarrior", Email = "PinkWarrior@PinkWarrior.com" };
    var mockStore = new Mock<IUserStore<ApplicationUser>>();

    var userManager = new UserManager<ApplicationUser>(mockStore.Object);
    mockStore.Setup(x => x.CreateAsync(dummyUser))
                .Returns(Task.FromResult(IdentityResult.Success));


    //Act
    Task<IdentityResult> tt = (Task<IdentityResult>)mockStore.Object.CreateAsync(dummyUser);
    var user = userManager.FindByName("PinkWarrior");

    //Assert
    Assert.AreEqual("PinkWarrior", user.UserName);
}

上面的user始终为空,因为我永远不会插入它。所以我遇到的问题是如何创建userManager,这不是模拟从模拟商店返回用户的?

This answer有些相似,但在这里没有回答我的问题。

任何帮助非常感谢

3 个答案:

答案 0 :(得分:16)

您需要模拟对FindByNameAsync的调用,因为这是UserManager将调用的内容:

public void Can_Create_User()
{
    //Arrange
    var dummyUser = new ApplicationUser() { UserName = "PinkWarrior", Email = "PinkWarrior@PinkWarrior.com" };
    var mockStore = new Mock<IUserStore<ApplicationUser>>();

    var userManager = new UserManager<ApplicationUser>(mockStore.Object);
    mockStore.Setup(x => x.CreateAsync(dummyUser))
                .Returns(Task.FromResult(IdentityResult.Success));

    mockStore.Setup(x => x.FindByNameAsync(dummyUser.UserName))
                .Returns(Task.FromResult(dummyUser));


    //Act
    Task<IdentityResult> tt = (Task<IdentityResult>)mockStore.Object.CreateAsync(dummyUser);
    var user = userManager.FindByName("PinkWarrior");

    //Assert
    Assert.AreEqual("PinkWarrior", user.UserName);
}

但是,我相信通过这样的测试,您正在测试Microsoft.AspNet.Identity.UserManager而不是您的代码。你所证明的是UserManager以某种方式调用你的mockStore。

Source code for Microsoft.AspNet.Identity包含这些类型的测试。

答案 1 :(得分:6)

MockHelper.cs git repo

中的测试中检查Identity课程

Identity GitHub repo linkClosed Issue for mocking

你应该找到有关模拟的灵感,例如

  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,
            null);
        validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<TUser>()))
            .Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
        return userManager;
    }

我正在使用这种方法:

       private UserController BuildCoontrollerWithDatabase()
    {
        DbContextOptionsBuilder dbContextOptionsBuilder = new DbContextOptionsBuilder();
        dbContextOptionsBuilder.UseInMemoryDatabase();

        ApplicationDbContext applicationDbContext = new ApplicationDbContext( dbContextOptionsBuilder.Options);

        var userStore = new UserStore<ApplicationUser>(applicationDbContext);

        UserManager<ApplicationUser>  userManager = TestUserManager<ApplicationUser>(userStore);

        return new UserController(userManager);


    }

答案 2 :(得分:2)

您的模拟用户存储未正确准备。因为它是一个模拟,你不应该期望mockStore.Object.CreateAsync会做任何事情,即它可以在任何地方添加任何东西。

您需要准备相应的&#34;阅读&#34;操作,因为很可能用户管理器将调用它。 (在模拟上设置FindByNameAsync方法以返回您需要的标识)。

在任何情况下,当您尝试测试框架类UserManager时,您尝试做的事情毫无意义。

实际上你需要的是模拟用户管理器本身,并在控制器中使用该模拟,或者在你使用该用户管理器的任何地方。