Monday, June 11, 2012

Mocking ASP.NET Objects with Microsoft Moles

We have a lot of legacy code in one of our ASP.NET projects and I was looking for ways to test it without having to refactor them too much. I started using Pex and Moles to generate some methods and see if they did the job for me. It hasn’t been a bad road so far. There have been some bumps and pits but nothing yet that has forced me to go back.

While I was writing unit tests using Moles, I did not find a lot of help on how we can mock some ASP.NET objects like query strings, for example. There are some teasers in this link here, but nothing that got me onto fourth gear. So I thought I will just ink down my findings on my journey so far in case it helps any of you. This post assumes that you already have Pex and Moles set up, so I am not going to deal with setting them up or creating a unit test using Pex.

I have code that reads the query string and based on the value of the query string returns a file name. This code is in the code behind of a user control. The code snippet looks like one below

   1:  protected virtual string GetFileName()
   2:  {
   4:          int queryStringValue;
   7:  if (HttpContext.Current.Request.QueryString["fileType"] != null && int.TryParse(HttpContext.Current.Request.QueryString["fileType"], out queryStringValue) == true)
   8:          {
   9:              switch (queryStringValue)
  10:              {
  11:                  case 1:
  12:                      strPageName = "Unix.html";
  13:                      break;
  14:                  case 2:
  15:                      strPageName = "Windows.html";
  16:                      break;
  17:                  case 3:
  18:                      strPageName = "iOS.html";
  19:                      break;
  20:                  case 4:
  21:                      strPageName = "Chrome.html";
  22:                      break;
  23:              }
  24:          }
  25:  }

Pay attention to the fact that this is a protected method and the method reads the value of the query string directly. No parameters are passed. If this was a new project, one of the suggestions would have been to pass the query string value as a parameter making this readily unit testable.

The Pex Method that I use to test this is given below

   1:  [PexMethod(MaxBranches = 20000)]
   2:          public string GetFileName(string communityValue)
   3:          {
   4:              System.Web.Moles.MHttpContext.CurrentGet = () =>
   5:              {
   6:                  return BHttpContext.SetCurrent();
   7:              };
   9:              MolesDelegates.Func<HttpRequest, NameValueCollection> queryStringMole;
  10:              queryStringMole = (nameVal) =>
  11:              {
  12:                  NameValueCollection queryString = new NameValueCollection(1);
  13:                  queryString.Add("fileType", "1");
  14:                  return queryString;
  15:              };
  16:              MHttpRequest.AllInstances.QueryStringGet = queryStringMole;
  17:              var target = UserControlWrapperFactory.Create();
  18:              string _fileName = target.getFileName();
  19:              return _fileName;
  20:          }
  21:      }

You will see that the code uses Moles to mock the HttpContext and the query string. We will get to the UserControlWrapperFactory in a minute but the query string itself is a simple implementation. A name value collection is created and then assigned to querystring get. Now, whenever your target code calls querystring[“somekey”] the code block inside MoleDelegates.Func gets executed. Though this example is about mocking query string, the same concept can be used to mock any ASP.NET object. In my tests, I have mocked ApplicationState, HttpRuntime Cache and HttpContext.Items all using similar code.

Now to deal with the UserControlWrapperFactory. As I already indicated above, the method in the user control is a protected method. So I am not going to be able to call this from the test method. To get around this, I created a user control wrapper that inherits from the user control I am testing.

   1:  public class UserControlWrapper: Controls_MyControl
   2:      {
   3:          public string getFileName()
   4:          {
   5:              return base.GetFileName();
   6:          }
   7:      }

The factory method just creates an instance of the wrapper and returns it.

Based on what I have worked with, I would strongly recommend Pex and Moles if you are looking to increase the code coverage from your unit testing and have hit a road block because you have objects that you are unable to mock. Before you start using it, also be aware that Pex and Moles are going to be replaced by Fakes in Visual Studio 2012 so you might have some code changes when you migrate. If you are looking for tutorials or documentation on Pex, try here first (especially Pex in the news and blogs section).

Happy Coding!!!


No comments:

Post a Comment