15

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.

Community
  • 1
  • 1
Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195
  • ActionExecutedContext is derived from ControllerContext. Haacked's answer is exactly about mocking ControllerContext - http://stackoverflow.com/questions/32640/mocking-asp-net-mvc-controller-context/32672#32672. In what exactly are you confused? – eu-ge-ne Jun 29 '09 at 11:33
  • Just haven't done it yet. I guess i lack knowledge of asp.net mvc innerworkings. :) – Arnis Lapsa Jun 29 '09 at 11:39
  • Then post your code. We will try to help :) – eu-ge-ne Jun 29 '09 at 11:41

3 Answers3

12

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
Mike Mayer
  • 169
  • 1
  • 8
eu-ge-ne
  • 28,023
  • 6
  • 71
  • 62
3

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! ^^

Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195
  • If it's working for you, that's cool, but the xUnit folks wrote about why they built it, which is worth a read: http://xunit.codeplex.com/wikipage?title=WhyDidWeBuildXunit&referringTitle=Home – ZeroBugBounce Jun 30 '10 at 21:22
  • @richdiet this one was long ago. I would prefer xUnit nowadays. – Arnis Lapsa Jun 30 '10 at 21:32
0

I know it is an old topic but it might be useful.

This works for me in ASP.NET Core 2.1. I only want to test a filter and to pass a fake action context there.

object resultValue = 123;
var actionContext = new ActionContext(new DefaultHttpContext(), 
                                      new RouteData(), 
                                      new ActionDescriptor());

var context = new ActionExecutedContext(actionContext,
                                        new List<IFilterMetadata>(), 
                                        new object())
                                        {
                                            Result = new ObjectResult(resultValue)
                                        };

IActionFilter filter = new MyFilter();
filter.OnActionExecuted(context);
Ramil Aliyev 007
  • 4,437
  • 2
  • 31
  • 47
  • I could be helpful if you could edit your answer to the form of unit test, see @ArnisLapsa answer. – KUTlime Mar 15 '21 at 17:56