I am trying to mock the UserStore's CreateAsync
method to have an in-memory user store.
public void Can_Create_User()
{
//Arrange
var dummyUser = new ApplicationUser() { UserName = "PinkWarrior", Email = "[email protected]" };
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);
}
The user
above is always null, because I'm never inserting it . So the problem I have is how can I make userManager,which isn't a mock return a user from my mock store?
This answer was somewhat similar but doesn't answer my question here.
Any help greatly appreciated
Check the MockHelper.cs
class from tests in Identity
git repo
Identity GitHub repo link or Closed Issue for mocking
You should find inspirations regarding mocks there, for example
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;
}
im using it with this method :
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);
}
You need to mock the call to FindByNameAsync, because that is what UserManager will call:
public void Can_Create_User()
{
//Arrange
var dummyUser = new ApplicationUser() { UserName = "PinkWarrior", Email = "[email protected]" };
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);
}
However, I believe with such test you are testing Microsoft.AspNet.Identity.UserManager and not your code. What you are proving is that UserManager somehow calls your mockStore.
Source code for Microsoft.AspNet.Identity contains these type of tests.
Your mocked user store is not prepared correctly. As it is a mock, you shouldn't expect that mockStore.Object.CreateAsync
will do anything, i.e. it's mot going to add anything anywhere.
You need to prepare the corresponding "read" operation, as most probably the user manager will invoke it. (setup the FindByNameAsync method on the mock to return the identity you need).
In any case what you are trying to do is pointless, as you are trying to test a framework class UserManager.
Probably what you need actually is to mock the user manager itself, and use that mock in your controller, or wherever you use that user manager.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With