Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Azure, PHP, OpenXML, VSTS, ...

About the author

Maarten Balliauw is currently employed as .NET Technical Consultant at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP and the Windows Azure cloud platform.
More about me More about me
Send mail E-mail me


ASP.NET MVC Quickly Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn
View Maarten Balliauw's MVP profile

Search

Latest Twitter

    Follow me on Twitter...

    My projects

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright Maarten Balliauw 2010

    ASP.NET MVC - Testing issues Q and A

    WTF? When playing around with the ASP.NET MVC framework and automated tests using Rhino Mocks, you will probably find yourself close to throwing your computer trough the nearest window. Here are some common issues and answers:

    Q: How to mock Request.Form?

    A: When testing a controller action which expects Request.Form to be a NameValueCollection, a NullReferenceException is thrown... This is due to the fact that Request.Form is null.

    Use Scott's helper classes for Rhino Mocks and add the following extension method:

    public static void SetupFormParameters(this HttpRequestBase request)
    {
        SetupResult.For(request.Form).Return(new NameValueCollection());
    }

    Q: I can't use ASP.NET Membership in my controller, every test seems to go bad...

    A: To test a controller using ASP.NET Membership, you should use a little trick. First of all, add a new property to your controller class:

    private MembershipProvider membershipProvider;

    public MembershipProvider MembershipProviderInstance {
        get {
            if (membershipProvider == null)
            {
                membershipProvider = Membership.Provider;
            }
            return membershipProvider;
        }
        set { membershipProvider = value; }
    }

    By doing this, you will enable the use of a mocked membership provider. Make sure you use this property in your controller instead of the standard Membership class (i.e. MembershipProviderInstance.ValidateUser(userName, password) instead of Membership.ValidateUser(userName, password)).

    Let's say you are testing a LoginController which should set an error message in the ViewData instance when authentication fails. You do this by creating a mocked MembershipProvider which is assigned to the controller. This mock object will be instructed to always shout "false" on the ValidateUser method of the MembershipProvider. Here's how:

    LoginController controller = new LoginController();
    var fakeViewEngine = new FakeViewEngine();
    controller.ViewEngine = fakeViewEngine;

    MockRepository mocks = new MockRepository();
    using (mocks.Record())
    {
        mocks.SetFakeControllerContext(controller);
        controller.HttpContext.Request.SetupFormParameters();

        System.Web.Security.MembershipProvider membershipProvider = mocks.DynamicMock<System.Web.Security.MembershipProvider>();
        SetupResult.For(membershipProvider.ValidateUser("", "")).IgnoreArguments().Return(false);

        controller.MembershipProviderInstance = membershipProvider;
    }
    using (mocks.Playback())
    {
        controller.HttpContext.Request.Form.Add("Username", "");
        controller.HttpContext.Request.Form.Add("Password", "");

        controller.Authenticate();

        Assert.AreEqual("Index", fakeViewEngine.ViewContext.ViewName);
        Assert.IsNotNull(
            ((IDictionary<string, object>)fakeViewEngine.ViewContext.ViewData)["ErrorMessage"]
        );
    }

    More questions? Feel free to ask! I'd be happy to answer them.

    kick it on DotNetKicks.com


    Code performance analysis in Visual Studio 2008

    Visual Studio developer, did you know you have a great performance analysis (profiling) tool at your fingertips? In Visual Studio 2008 this profiling tool has been placed in a separate menu item to increase visibility and usage. Allow me to show what this tool can do for you in this walktrough.

    An application with a smell…

    Before we can get started, we need a (simple) application with a “smell”. Create a new Windows application, drag a TextBox on the surface, and add the following code:

    private void Form1_Load(object sender, EventArgs e)
    {
        string s = "";
        for (int i = 0; i < 1500; i++)
        {
            s = s + " test";
        }
        textBox1.Text = s;
    }

    You should immediately see the smell in the above code. If you don’t: we are using string.Concat() for 1.500 times! This means a new string is created 1.500 times, and the old, intermediate strings, have to be disposed again. Smells like a nice memory issue to investigate!

    Profiling

    Performance wizardThe profiling tool is hidden under the Analyze menu in Visual Studio. After launching the Performance Wizard, you will see two options are available: sampling and instrumentation. In a “real-life” situation, you’ll first want to sample the entire application searching for performance spikes. Afterwards, you can investigate these spikes using instrumentation. Since we only have one simple application, let’s instrumentate immediately.

    Upon completing the wizard, the first thing we’ll do is changing some settings. Right-click the root node, and select Properties. Check the “Collect .NET object allocation information” and “Also collect .NET object lifetime information” to make our profiling session as complete as possible:

    Profiling property pages

    Launch with profilingYou can now start the performance session from the toolpane. Note that you have two options to start: Launch with profiling and Launch with profiling paused. The first will immediately start profiling, the latter will first start your application and wait for your sign to start profiling. This can be useful if you do not want to profile your application startup but only a certain event that is started afterwards.

    After the application run, simply close it and wait for the summary report to appear:

    Performance Report Summary 1

    WOW! Seems like string.Concat() is taking 97% of the application’s memory! That’s a smell indeed... But where is it coming from? In a larger application, it might not be clear which method is calling string.Concat() this many times. To discover where the problem is situated, there are 2 options…

    Discovering the smell – option 1

    Option 1 in discovering the smell is quite straight-forward. Right-click the item in the summary and pick Show functions calling Concat:

    Functions allocating most memory

    You are now transferred to the “Caller / Callee” view, where all methods doing a string.Concat() call are shown including memory usage and allocations. In this particular case, it’s easy to see where the issue might be situated. You can now right-click the entry and pick View source to be transferred to this possible performance killer.

    Possible performance killer

    Discovering the smell – option 2

    Visual Studio 2008 introduced a cool new way of discovering smells: hotpath tracking. When you move to the Call Tree view, you’ll notice a small flame icon in the toolbar. After clicking it, Visual Studio moves down the call tree following the high inclusive numbers. Each click takes you further down the tree and should uncover more details. Again, string.Concat() seems to be the problem!

    Hotpath tracking

    Fixing the smell

    We are about to fix the smell. Let’s rewrite our application code using StringBuilder:

    private void Form1_Load(object sender, EventArgs e)
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 1500; i++)
        {
            sb.Append(" test");
        }
        textBox1.Text = sb.ToString();
    }

    In theory, this should perform better. Let’s run our performance session again and have a look at the results:

    Performance Report Summary 2

    Compare Peformance ReportsSeems like we fixed the glitch! You can now investigate further if there are other problems, but for this walktrough, the application is healthy now. One extra feature though: performance session comparison (“diff”). Simply pick two performance reports, right-click and pick Compare performance reports. This tool will show all delta values (= differences) between the two sessions we ran earlier:

    Comparison report 

    Update 2008-02-14: Some people commented on not finding the Analyze menu. This is only available in the Developer or Team Edition of Visual Studio. Click here for a full comparison of all versions.

    Update 2008-05-29: Make sure to check my post on NDepend as well, as it offers even more insight in your code!

    kick it on DotNetKicks.com