I was having a bit of issue when I tried to test my class which needs
UserManager<ApplicationUser> object and
RoleManager<IdentityRole> object in constructor method. Both classes are from new membership system called ASP.NET Core Identity. You can learn more from Introduction to Identity on ASP.NET Core
When I first googled for my problem, some people use Fake class to test their method which results with more classes in unit test project to maintain. I rather try to avoid that.
The solution that I have used Moq for .NET mocking framework. Without creating fake class, I can instantiate a Mock object by passing in mocked arguments into the intended type contructor method.
Please see example below:
var mockUserManager = new Mock<UserManager<ApplicationUser>>( new Mock<IUserStore<ApplicationUser>>().Object, new Mock<IOptions<IdentityOptions>>().Object, new Mock<IPasswordHasher<ApplicationUser>>().Object, new IUserValidator<ApplicationUser>, new IPasswordValidator<ApplicationUser>, new Mock<ILookupNormalizer>().Object, new Mock<IdentityErrorDescriber>().Object, new Mock<IServiceProvider>().Object, new Mock<ILogger<UserManager<ApplicationUser>>>().Object); return mockUserManager.Object;
var mockRoleManager = new Mock<RoleManager<IdentityRole>>( new Mock<IRoleStore<IdentityRole>>().Object, new IRoleValidator<IdentityRole>, new Mock<ILookupNormalizer>().Object, new Mock<IdentityErrorDescriber>().Object, new Mock<ILogger<RoleManager<IdentityRole>>>().Object); return mockRoleManager.Object;
As observed above, ASP.NET Identity's
UserManager<TUser> takes quite a number of parameters if you look at the class definition. And there is no parameterless constructor in
UserManager<TUser>, otherwise, you will have an error message saying Could not find a parameterless constructor. like I did when trying to instantiate this class without constructor parameters. By the way, I was using Castle Windsor for Inversion of Control (IOC) container for my unit testing project for injecting required arguments into contructor methods.
So by using Mocked object from Moq, I would be able to use
Mock<UserManager<TUser>().Setup(x => ...).Return(...) in all my test methods.