I'm trying to unit test an MVC 6 controller that directly interacts with this.HttpContext.Authentication
for authentication. I'm not using the Identity Framework, but rather am interacting with Cookie Authentication middleware directly.
Following some examples I've seen by MS, I've been using DefaultHttpContext for testing purposes. The problem is that the AuthenticationManager property on DefaultHttpContext is read-only so I'm unsure how I can mock it.
If I don't mock it, I receive an error stating "No authentication handler is configured to handle the scheme: Cookies" in my tests when calling:
HttpContext.Authentication.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal, authProperties);
I had the same problem and i finally did it with some level of mocking I use Moq
var claimPrincipal = new ClaimsPrincipal();
var mockAuth = new Mock<AuthenticationManager>();
mockAuth.Setup(c => c.SignInAsync("YourScheme", claimPrincipal)).Returns(Task.FromResult("done"));
var mockContext = new Mock<HttpContext>();
mockContext.Setup(c => c.Authentication).Returns(mockAuth.Object);
var fakeActionContext = new ActionContext(mockContext.Object, new RouteData(), new ControllerActionDescriptor());
var contContext = new ControllerContext(fakeActionContext);
then you pass that controller context to you controller you want to test
var controller = new TestedController(Your attribute)
{
ControllerContext = contContext
};
The accepted answer is now deprecated by MS who recommend against using the AuthenticationManager and instead using the extension methods. An alternative is below. Note that the additional two services added are because setting RequestServices removes some defaults which would otherwise be created by DefaultHttpContext.
var context = new ControllerContext();
context.HttpContext = new DefaultHttpContext();
context.HttpContext.User = userMock.Object; // If needed
context.HttpContext.Session = sessionMock.Object; // If needed
var authManager = new Mock<IAuthenticationService>();
authManager.Setup(s => s.SignOutAsync(It.IsAny<HttpContext>(),
CookieAuthenticationDefaults.AuthenticationScheme,
It.IsAny<Microsoft.AspNetCore.Authentication.AuthenticationProperties>())).
Returns(Task.FromResult(true));
var servicesMock = new Mock<IServiceProvider>();
servicesMock.Setup(sp => sp.GetService(typeof(IAuthenticationService))).Returns(authManager.Object);
servicesMock.Setup(sp => sp.GetService(typeof(IUrlHelperFactory))).Returns(new UrlHelperFactory());
servicesMock.Setup(sp => sp.GetService(typeof(ITempDataDictionaryFactory))).Returns(new TempDataDictionaryFactory(new SessionStateTempDataProvider()));
context.HttpContext.RequestServices = servicesMock.Object;
// Use context to pass to your controller
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