MSTest: Unit Testing HttpContext.SignoutAsync for the logout - mstest

Simply passing Mock HttpContext to the controller context while unit testing logout functionality will throw following error
HttpContext.Signout + value can not be null (Parameter 'provider')
var mockHttpContext = new Mock<HttpContext>();
//set the controller HttpContext
_controller.ControllerContext.HttpContext = mockHttpContext.Object;
// Now call the Logout action method and Test result

If you drill down to the definition of SigOutAsync code it expect Authentication Service Provider which should not be null .
Hence , along with mocking HttpContext you also need to mock the service provider which will solve the issue .
//mock the Http Context along with Service provider
var mockHttpContext = new Mock<HttpContext>();
var authServiceMock = new Mock<IAuthenticationService>();
authServiceMock.Setup(_ => _.SignOutAsync(It.IsAny<HttpContext>(), It.IsAny<string>(),It.IsAny<AuthenticationProperties>())).Returns(Task.FromResult((object)null));
var serviceProviderMock = new Mock<IServiceProvider>();
serviceProviderMock.Setup(_ => _.GetService(typeof(IAuthenticationService)))
.Returns(authServiceMock.Object);
mockHttpContext.Setup(x => x.RequestServices)
.Returns(serviceProviderMock.Object);
//set the controller HttpContext
_controller.ControllerContext.HttpContext = mockHttpContext.Object;
// Now call the Logout and Test
Similar logic can be applied while testing SignIn functionality
Refer here as well- How to unit test HttpContext.SignInAsync()?

Related

Web API: how to read action attribute and parameters from HttpContext

In regular class, I need to read following from the HttpContext:
Controller and action name
Action's attribute (I could get that through HttpActionContext.ActionDescriptor.GetCustomAttributes<type>() but here I don't have HttpActionContext - I only have HttpContext)
Read argument (like actionContext.ActionArguments["paramName"], but again - I only have a HttpContext)
It's not an action filter and not a controller class. But, I can access HttpContext.
From asp.net core 3.0 https://stackoverflow.com/a/60602828/10612695
public async Task Invoke(HttpContext context)
{
// Get the enpoint which is executing (asp.net core 3.0 only)
var executingEnpoint = context.GetEndpoint();
// Get attributes on the executing action method and it's defining controller class
var attributes = executingEnpoint.Metadata.OfType<MyCustomAttribute>();
await next(context);
// Get the enpoint which was executed (asp.net core 2.2 possible after call to await next(context))
var executingEnpoint2 = context.GetEndpoint();
// Get attributes on the executing action method and it's defining controller class
var attributes2 = executingEnpoint.Metadata.OfType<MyCustomAttribute>();
}

Web API - Get information encrypted inside token, ticket ExpiresUtc and IssuedUtc

I am using Web API as my back-end and implemented the token security using the built in mechanism. In the template code, when issuing the access token, I can get the issued and expired dates of the token:
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
var issued = context.Properties.IssuedUtc;
var expired = context.Properties.ExpiresUtc;
.
.
.
}
Now when a request is made to a method that requires authorization I want to do something similar:
[Authorize]
public async Task<string> GetTokenInfo()
{
//var issued = GetCurrentTicket().Properties.ExpiresUtc;
//var issued = GetCurrentTicket().Properties.IssuedUtc;
.
.
.
}
So how can I get the information encrypted inside the token, more specifically the ExpireUtc and IssuedUtc ?
You can easily retrieve the AuthenticationProperties dictionary using IAuthenticationManager.AuthenticateAsync, which returns a AuthenticateResult object: https://msdn.microsoft.com/en-us/library/dn270674(v=vs.113).aspx
From a Web API controller, you'll need the GetOwinContext extension to get the OWIN context from the request message and use IOwinContext.Authentication: https://msdn.microsoft.com/en-us/library/system.net.http.owinhttprequestmessageextensions.getowincontext(v=vs.118).aspx
var context = Request.GetOwinContext();
var result = await context.Authentication.AuthenticateAsync(OAuthDefaults.AuthenticationType);
if (result == null) {
throw new InvalidOperationException();
}
var properties = result.Properties;
(of course, you also need to have a properly configured app.UseOAuthBearerAuthentication call in your Startup class, but I assume it's the case here).

How to mock httpcontext so that it is not null from a unit test?

I am writing a unit test and the controller method is throwing an exception because HttpContext / ControllerContext is null. I don't need to assert anything from the HttpContext, just need it to be not NULL. I have done research and I believe Moq is the answer. But all the samples that I have seen haven't helped me a lot. I don't need to do anything fancy, just to mock the httpcontext. Point me in the right direction!
Got these two functions from here in a class;
public static class HttpContextFactory
{
public static void SetFakeAuthenticatedControllerContext(this Controller controller)
{
var httpContext = FakeAuthenticatedHttpContext();
ControllerContext context =
new ControllerContext(
new RequestContext(httpContext,
new RouteData()), controller);
controller.ControllerContext = context;
}
private static HttpContextBase FakeAuthenticatedHttpContext()
{
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();
var user = new Mock<IPrincipal>();
var identity = new Mock<IIdentity>();
context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session.Object);
context.Setup(ctx => ctx.Server).Returns(server.Object);
context.Setup(ctx => ctx.User).Returns(user.Object);
user.Setup(ctx => ctx.Identity).Returns(identity.Object);
identity.Setup(id => id.IsAuthenticated).Returns(true);
identity.Setup(id => id.Name).Returns("a.ali174");
return context.Object;
}
}
From the unit test I called them as such;
HttpContextFactory.SetFakeAuthenticatedControllerContext(controller);
Make sure you have Moq installed in your tests project:
Install-Package Moq
I know this is an older subject, however Mocking a MVC application for unit tests is something we do on very regular basis.
I just wanted to add my experiences Mocking a MVC 3 application using Moq 4 after upgrading to Visual Studio 2013. None of the unit tests were working in debug mode and the HttpContext was showing "could not evaluate expression" when trying to peek at the variables.
Turns out visual studio 2013 has issues evaluating some objects. To get debugging mocked web applications working again, I had to check the "Use Managed Compatibility Mode" in Tools=>Options=>Debugging=>General settings.

HttpContext.Current Request "Not Available" while running "Local IIS Web Server

I was trying to work with the http context (with the help of Httpcontext.current) in the application_start event in global.asax then you will receive an Error:- HttpContext.Current Request is not available in this context.
The problem can easily be worked with a workaround by using a static constructor, which is fired when the object is accessed first. We can keep a flag in the Application_Beginrequest event and easily determine the request that initialized the application.
But in this case it gets created at every request, which is not required for me. I want to create or access Httpcontext.current once
My Code Is as Follows :-
`//var context = new HttpContextWrapper(HttpContext.Current);
//var routeData = RouteTable.Routes.GetRouteData(context) ?? new RouteData();
//var requestContext = new RequestContext(context, routeData);
//var urlHelper = new UrlHelper(requestContext);
//var url = urlHelper.Action("Home", "Index");
var httpContext = new HttpContextWrapper(HttpContext.Current);
UrlHelper urlHelper = new UrlHelper(new RequestContext(httpContext, new RouteData()));
if (urlHelper.RequestContext.HttpContext.Request.IsLocal)
{
}
//if (((requestContext.HttpContext).Request).IsLocal)
//{
//}`
There is no HttpContext nor HttpRequest instance in App_Start in integrated mode. You must work around this. If you really need to do something on first request, then register new BeginRequest handler in your global.asax and then unregister it when you are done.

ASP.NET MVC MOQ - Modifed public ActionResult LogOn to include Session Object - Unit Test Failing

I'm pretty new to Unit Testing and MOQ etc. I've modified public ActionResult LogOn(LogOnModel model) Action to inlclude Session["UserFullName"] for logging purpose.
Unfortunately, the Unit Test is failing with Object Reference not set for Session["UserFullName"].
Could anyone please tell me how to resolive this issue using MOQ by modifying GetAccountController() method on unit test?
Regards.
The HttpSessionStateBase is made available through the HttpContextBase. You can set the HttpContextBase via the ControllerContext. This is how I do it using RhinoMocks.
var httpContext = MockRepository.GenerateMock<HttpContextBase>();
var session = MockRepository.GenerateMock<HttpSessionStateBase>();
httpContext.Expect( c => c.Session ).Return( session ).Repeat.AtLeastOnce();
session.Expect( s => s["UserFullName"] ).Return( "John Q. User" );
var controller = GetAccountController();
controller.ControllerContext = new ControllerContext( httpContext, new RouteData(), controller );
...

Resources