How-to test action filters in ASP.NET MVC?
-
21-08-2019 - |
Question
Need some pointers for this. Found this and this, but I'm still kind a confused.
I just want to mock ActionExecutedContext, pass it, let filter to work a bit and check result.
Any help?
Source of filter you can find here
(it's changed a bit, but that's not a point at the moment).
So - i want unit test, that RememberUrl filter is smart enough to save current URL in session.
Solution
1) Mocking Request.Url in ActionExecutedContext:
var request = new Mock<HttpRequestBase>();
request.SetupGet(r => r.HttpMethod).Returns("GET");
request.SetupGet(r => r.Url).Returns(new Uri("http://somesite/action"));
var httpContext = new Mock<HttpContextBase>();
httpContext.SetupGet(c => c.Request).Returns(request.Object);
var actionExecutedContext = new Mock<ActionExecutedContext>();
actionExecutedContext.SetupGet(c => c.HttpContext).Returns(httpContext.Object);
2) Suppose you are injecting session wrapper in your RememberUrlAttribute's public constructor.
var rememberUrl = new RememberUrlAttribute(yourSessionWrapper);
rememberUrl.OnActionExecuted(actionExecutedContext.Object);
// Then check what is in your SessionWrapper
OTHER TIPS
This is the result:
#region usages
using System;
using System.Collections.Specialized;
using System.Web;
using System.Web.Mvc;
using x.TestBase;
using x.UI.y.Infrastructure.Enums;
using x.UI.y.Infrastructure.Filters;
using x.UI.y.Test.Mocks;
using Moq;
//considering switch to NUnit... :D
using Microsoft.VisualStudio.TestTools.UnitTesting;
#endregion
namespace x.UI.y.Test.Unit.Infrastructure.Filters
{
[TestClass]
public class RememberUrlTester : TesterBase
{
private static HttpContextBaseMock _context =
new HttpContextBaseMock();
private static ActionExecutedContextMock _actionContext =
new ActionExecutedContextMock(_context.Object);
[TestMethod]
//"Can save url in session" (i prefer test names in my own language :)
public void SpeejPieglabaatUrlSesijaa()
{
//Arrange
const string _url = "http://www.foo.bar/foo?bar=bar";
_context.RequestMock.SetUrl(_url);
var filter = new RememberUrlAttribute();
//Act
filter.OnActionExecuted(_actionContext.Object);
//Assert
_context.SessionMock.Verify
(m => m.Add(SessionKey.PreviousUrl.ToString(), _url));
}
}
}
Wrapped Mock<HttpWhatever> to keep tests clean.
I'm sure things can be done better, but I think it's a great start and I'm feeling quite excited.
Finally that HttpContext monster is under control! ^^