Question

Using C# I'm trying to unit test controller actions and time how long it takes for them to return. I'm using the unit testing framework built into VS2012 Ultimate.

Unfortunately I'm also trying to wrap my head around TestContext and how to use it..

Some example code (my controller action):

[HttpPost]
public JsonResult GetUserListFromWebService()
{
    JsonResult jsonResult = new JsonResult();
    WebService svc = new WebService();
    jsonResult.Data = svc.GetUserList(User.Identity.Name);
    return jsonResult;
}

When I try to unit test this, User.Identity.Name is null so it throws an exception. My current unit test code looks like:

[TestClass]
public class ControllerAndRepositoryActionTests {
    public TestContext testContext { get; set; }
    private static Repository _repository;
    private username = "domain\\foobar";
    private static bool active = true;

    [ClassInitialize]
    public static void MyClassInitialize(TestContext testContext)
    {
        _repository = new WebServiceRepository();
    }

    #region Controller method tests
    [TestMethod]
    public void GetUserListReturnsData() 
    {
        Controller controller = new Controller();
        var result = controller.GetUserListFromWebService();
        Assert.IsNotNull(result.Data);
    }
    #endregion

    #region service repository calls - with timing
    [TestMethod]
    public void GetUserListTimed()
    {
        testContext.BeginTimer("Overall"); 
        var results = _repository.GetUserList(username, active);
        foreach (var result in results)
        {
            Console.WriteLine(result.UserID);
            Console.WriteLine(result.UserName);
        }
        testContext.EndTimer("Overall");
    }
    #endregion 
}

Can I use TestContext to set the User.Identity that will be eventually used in the GetUserListFromWebService call?

If I can, what is the accepted way to assign TestContext. When I get it as a param in MyClassInitialize do I set my member variable, or am I supposed to pass it as a param to the TestMethods in some way?

Am I completely missing the point and should I be using some other mocking framework?

Was it helpful?

Solution

To make this test to work, I should change the signature of your class. Because you can not make a stub or a mock of your class Webservice, because you are creating it in the method.

class YourClass
{
   private readeonly WebService _ws;
   public YourClass(WebService ws)
   {
       _ws=ws;
   }

   [HttpPost]
   public JsonResult GetUserListFromWebService()
   {
       JsonResult jsonResult = new JsonResult();
       jsonResult.Data = _ws.GetUserList(User.Identity.Name);
       return jsonResult;
   }
}

Now you can in your test easily mock the class WebService with Moq or other frameworks. To make it eaven easier you shoul create an interface to your class WebService that implements the method GetUserList();

And to mock the User.Identy

public SomeController CreateControllerForUser(string userName) 
{
    var mock = new Mock<ControllerContext>();
    mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(userName);
    mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);

    var controller = new SomeController();
    controller.ControllerContext = mock.Object;

    return controller;
}

Or read this blog post http://weblogs.asp.net/rashid/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top