Mocking new Microsoft Entity Framework Identity UserManager and RoleManager

20,892

Solution 1

Alternatively, you can mock the IUserStore<TUser> interface that UserManager accepts as an argument.

var userStore = new Mock<IUserStore<ApplicationUser>>();
var userManager = new UserManager(userStore.Object);

As @Joe Brunscheon notes in the comment below, UserManager detects support for other interfaces like IUserPasswordStore, etc. You can also moq those:

var passwordManager = userStore.As<IUserPasswordStore<ApplicationUser>>()
    .Setup(...).Returns(...);

You don't have to moq out all of these at once, you can just moq them up as needed by your code-under-test. In reality, the UserStore that EF uses to implement IUserStore implements other interfaces, and UserManager will do internal detection to see if these interfaces are implemented, and therefore, additional features supported. Fortunately, moq lets you mock up a surrogate that can implement many interfaces, using .As<T>().

In short, Microsoft.AspNet.Identity does give you everything you need to use it bare, without a wrapper, in your code. As long as you use dependency injection to instantiate your UserManager, you can safely moq it in unit tests by mocking up the interfaces it consumes and passing them via some kind of IUserStore<T> moq that is augmented to support methods on other interfaces internally detected by UserManager.

Solution 2

I like to update the solution to this question for anyone who works on asp.net core:

    private Mock<UserManager<ApplicationUser>> GetMockUserManager()
    {
        var userStoreMock = new Mock<IUserStore<ApplicationUser>>();
        return new Mock<UserManager<ApplicationUser>>(
            userStoreMock.Object, null, null, null, null, null, null, null, null);
    }

Yes, 8 times null but so far there isn't any more graceful solution. If you are interested on the other parameters, take a look at the source code.

Solution 3

Just to expand on Rubito's answer, here is how I did it for RoleManager:

public static Mock<RoleManager<ApplicationRole>> GetMockRoleManager()
{
   var roleStore = new Mock<IRoleStore<ApplicationRole>>();
   return new Mock<RoleManager<ApplicationRole>>(
                roleStore.Object,null,null,null,null);

}

Solution 4

You won't be able to Mock UserManager or RoleManager directly. What you CAN do, however, is mock an object that uses them.

For Example:

public interface IWrapUserManager
{
    UserManager WrappedUserManager {get; set;}
    //provide methods / properties that wrap up all UserManager methods / props.
}

public class WrapUserManager : IWrapUserManager
{
    UserManager WrappedUserManager {get; set;}
    //implementation here. to test UserManager, just wrap all methods / props.
}

//Here's a class that's actually going to use it.
public class ClassToTest
{
    private IWrapUserManager _manager;
    public ClassToTest(IWrapUserManager manager)
    {
        _manager = manager;
    }
    //more implementation here
}

On to the mocking:

[TestClass]
public class TestMock
{
    [TestMethod]
    public void TestMockingUserManager()
    {
        var mock = new Mock<IWrapUserManager>();
        //setup your mock with methods and return stuff here.
        var testClass = new ClassToTest(mock.Object); //you are now mocking your class that wraps up UserManager.
        //test your class with a mocked out UserManager here.
    }
}

Solution 5

public class FakeUserManager : UserManager<User>
    {
        public FakeUserManager() 
            : base(new Mock<IUserStore<User>>().Object,
                  new Mock<IOptions<IdentityOptions>>().Object,
                  new Mock<IPasswordHasher<User>>().Object,
                  new IUserValidator<User>[0],
                  new IPasswordValidator<User>[0],
                  new Mock<ILookupNormalizer>().Object, 
                  new Mock<IdentityErrorDescriber>().Object,
                  new Mock<IServiceProvider>().Object,
                  new Mock<ILogger<UserManager<User>>>().Object, 
                  new Mock<IHttpContextAccessor>().Object)
        { }

        public override Task<User> FindByEmailAsync(string email)
        {
            return Task.FromResult(new User{Email = email});
        }

        public override Task<bool> IsEmailConfirmedAsync(User user)
        {
            return Task.FromResult(user.Email == "[email protected]");
        }

        public override Task<string> GeneratePasswordResetTokenAsync(User user)
        {
            return Task.FromResult("---------------");
        }
    }
Share:
20,892

Related videos on Youtube

Dale Alleshouse
Author by

Dale Alleshouse

Updated on July 09, 2022

Comments

  • Dale Alleshouse
    Dale Alleshouse almost 2 years

    Has anyone come up with a successful mocking solution for UserManager and RoleManager? I have been beating my head against a wall all day. All I want to do is mock the objects to use an in memory collection rather than hitting the Entity Framework data store. I've scoured the internet and tried several different approaches using MOQ.

    I was under the impression that the new stuff was much easier to test. Am I missing something?

  • Joe Brunscheon
    Joe Brunscheon over 10 years
    IUserStore doesn't provide all the functionality of UserManager. The basics are there, but there is a lot more in UserManager that would likely need to be mocked out in order to get good test coverage over classes that use UserManager.
  • Dale Alleshouse
    Dale Alleshouse over 10 years
    Thank you for your quick reply. I decided to try to use a fake rather than trying to Mock. I created a new instance of 'IdentityDbContext<ApplicationUser>' using an in memory DbSet and passed that into the 'IUserStore' constructor. For some reason, it acts as if my DbSets are always empty. I verified that I can query users and roles directly from the IdentityDbContext object. I wonder if this should be a separate question...
  • Joy
    Joy over 9 years
    I stumbled upon this same question . However mocking with IUserStore<T> with DbContext and then passing it to UserManager Seems too much work . So I straight used DI container to get 'MyUserManager' . In that manner the object graph testability is guarenteed via container.verify() method . So that If any of the dependency graph for asp.net identity breaks , the test would fail as container.verify() would throw exception
  • danludwig
    danludwig over 9 years
    @Joy that is definitely one way you can do it, but that is technically not a unit test, it is an integration test. You are testing the integration of the IUserStore with your IoC container.
  • Joy
    Joy over 9 years
    @danludwig So you mean if we need to unit test . We need to mock or fake each and every single object of the object graph ? So just to test UserManager.CreateAsync() or UserManager.DeleteAsync() method ? After all I am testing only one single responsibility for my business logic . Does it realy pay off to mock all the dependencies explicitly for single class instead of using DI container ? Just to test one single functionality ?
  • danludwig
    danludwig over 9 years
    @Joy You shouldn't need to fake / mock each and every object in the dependency graph, only those that are used by the Method Under Test. "Does it really pay off" is a subjective question... how much revenue does the app generate, the volatility of your customers & market, and the payroll of your developers will help answer that question. Also I am not saying that integration tests are bad and you should do unit tests instead. I was just pointing out the difference. In reality, you should have both unit tests and integration tests, as well as user acceptance tests (if the are worth having).
  • Moritz Schmidt
    Moritz Schmidt about 7 years
    Does this still work? Visual Studio doesnt know ApplicationUser in my case
  • rubito
    rubito about 7 years
    ApplicationUser is created by the asp.net core project template. If you aren't using that template, then try out 'IdentityUser' since that is the root class from which ApplicationUser inherits from.
  • Moritz Schmidt
    Moritz Schmidt almost 7 years
    Is it possible to Mock a useful UserStore? It seem's really hard to mock a working DbContext class.. Any experience with that? :-)
  • Marshall Tigerus
    Marshall Tigerus about 6 years
    @MoritzSchmidt sorry for the necro, but define an interface that your DbContext implements and mock that instead. Then the hard part is mocking the DbSets properly, but you can get most of that functionality pretty easily: jankowskimichal.pl/en/2016/01/…
  • Marshall Tigerus
    Marshall Tigerus about 6 years
    to take this one step further (and easier) you can define an IUserManager interface yourself, create an empty subclass that implements it and replace your references to UserManager with the interface.
  • mbrookson
    mbrookson almost 5 years
    There is a small issue with this answer which is that you need to add the generic type when instantiating the UserManager class e.g. new UserManager<ApplicationUser>();