ASP.NET 5 Unit Test Controller with UserManager

I started using ASP.NET 5 (vNext), and now I'm trying to use the unit test controller, which uses the UserManager to register and login.

I am using xUnit and moq.netcore .

In my UnitTest, I have:

var mockStore = new Mock<IUserStore<ApplicationUser>>(MockBehavior.Strict).As<IUserPasswordStore<ApplicationUser>>(); mockStore.Setup(x => x.CreateAsync(It.IsAny<ApplicationUser>(), CancellationToken.None)).Returns(Task.FromResult(new IdentityResult())); var userManager = new UserManager<ApplicationUser>(mockStore.Object, null, null, null, null, null, null, null, null, null); 

And the code in the controller:

 var result = await _securityManager.CreateAsync(user, model.Password); 

But when I run unit test, I get a null exception when calling CreateAsync.

I don’t understand why I can’t mock the CreateAsync method with the ApplicationUser and string parameters, and I have to mock it using the CancellationToken.

This is my first project using ASP.NET 5, I used to use ASP.NET 4.6, so now a lot more.

And do you think I should already be developing an important project in ASP.NET 5 or should I wait and develop it for ASP.NET 4.6?

+5
source share
1 answer

After trying a lot of things, I came up with a working solution.

Usermanager

I created the FakeUserManager class, which inherits the UserManager and overrides the CreateAsync method.

 public class FakeUserManager : UserManager<ApplicationUser> { public FakeUserManager() : base(new Mock<IUserStore<ApplicationUser>>().Object, new Mock<IOptions<IdentityOptions>>().Object, new Mock<IPasswordHasher<ApplicationUser>>().Object, new IUserValidator<ApplicationUser>[0], new IPasswordValidator<ApplicationUser>[0], new Mock<ILookupNormalizer>().Object, new Mock<IdentityErrorDescriber>().Object, new Mock<IServiceProvider>().Object, new Mock<ILogger<UserManager<ApplicationUser>>>().Object, new Mock<IHttpContextAccessor>().Object) { } public override Task<IdentityResult> CreateAsync(ApplicationUser user, string password) { return Task.FromResult(IdentityResult.Success); } } 

Then I passed a new instance of FakeUserManager to the AccountController constructor, and it works fine.


SignInManager

And for those who might need a SignInManager fake, I did it like this:

I created a FakeSignInManager class that inherits SignInManager and overrides the methods I need.

 public class FakeSignInManager : SignInManager<ApplicationUser> { public FakeSignInManager(IHttpContextAccessor contextAccessor) : base(new FakeUserManager(), contextAccessor, new Mock<IUserClaimsPrincipalFactory<ApplicationUser>>().Object, new Mock<IOptions<IdentityOptions>>().Object, new Mock<ILogger<SignInManager<ApplicationUser>>>().Object) { } public override Task SignInAsync(ApplicationUser user, bool isPersistent, string authenticationMethod = null) { return Task.FromResult(0); } public override Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure) { return Task.FromResult(SignInResult.Success); } public override Task SignOutAsync() { return Task.FromResult(0); } } 

And since SignInManager is needed to access the context for work, I made FakeSignInManager get it in the constructor.

Then, before creating a new instance of SignInManager, I will prepare a new HttpContextAccessor as follows:

 var context = new Mock<HttpContext>(); var contextAccessor = new Mock<IHttpContextAccessor>(); contextAccessor.Setup(x => x.HttpContext).Returns(context.Object); 

And then create a new instance of FakeSignInManager:

 new FakeSignInManager(contextAccessor.Object); 
+9
source

Source: https://habr.com/ru/post/1243850/


All Articles