Mayukh Ganguly
Mayukh Ganguly

Reputation: 55

Finding difficulty in unit testing a Controller Action method using NUnit

I want to Unit test the method ExecLogin() using NUnit testing framework. But I'm having problem while writing code for the testing because the GenerateInput() method is declared as internal virtual. So, I'm not being able pass the SessionUserId parameter to it which I think is needed. Please guide me how to write the unit test code for ExecLogin(). I'm new to testing.

This is related to ASP.NET MVC3 testing controller actions.

    public class BaseController : Controller
    {
        public string SessionUserId
        {
            get { return Session["UserId"] as string; }
            set { Session["UserId"] = value; }
        }

        internal virtual SomeType GenerateInput(SomeType inputData)
        {
             var finalInput = new StringBuilder(600);

             finalInput.Append("<Root>")
             .Append("<UserId>")
             .Append(SessionUserId)
             .Append("</UserId>")
             .Append("<IPAddress>")
             .Append(this.GetClientIpAddress())
             .Append("</IPAddress>")
             .Append(inputData.InputValue)
             .Append("</Root>");

             inputData.InputValue = finalInput.ToString();
             return inputData;
        }
    }

    public class LoginController : BaseController
    {
        [HttpPost]
        public JsonResult ExecLogin(JsonRequest<LoginModel> request)
        {
            var loginObj = request.InputObject;

            var login = new StringBuilder(300);
            login.Append("<UserName>").Append(loginObj.UserName).Append("</UserName>")
                .Append("<Password>").Append(EncodingHelper.GetHashedPassword(loginObj.Password)).Append("</Password>")
                .Append("<RememberMe>").Append(loginObj.RememberMe).Append("</RememberMe>")
                ;
        var input = new SomeType { Operation = request.Operation, PageName = ActionName, InputValue = login.ToString() };

        var returnValue = SomeDelegate.Instance.ExecuteOperation(GenerateInput(input));
        return Json(new JsonResponse<string> { Status = returnValue.Status, Result = this.PopulateSession(returnValue) });
        }
    }

This is our model classes:

   public class LoginModel
   {
       public string UserId { get; set; }
       public string UserName { get; set; }
       public string Password { get; set; }
       public bool RememberMe { get; set; }
       public bool IsValidUser { get; set; }
   }

   public class JsonRequest<T>
   where T : class
   {
       public string Operation { get; set; }
       public T InputObject { get; set; }
   }

While learning Dependency Injection pattern I came to know that use of concrete classes makes code more tightly coupled. And the more tightly coupled the code the harder it becomes to test. Is this why I'm not being able to test it properly? Please help.

Upvotes: 2

Views: 604

Answers (1)

AlSki
AlSki

Reputation: 6961

This is actually part of a common pattern, how to provide additional hook points for testing without disturbing the interface that is publicly available, and fortunately internal is your friend here.

I assume the problem is that you have 2 assemblies, let's call them MyCode.dll and MyCode.Tests.dll for simplicity. This means that MyCode.Tests cannot access the internal methods of MyCode because, well basically it isnt internal :-)

If you go to your AssemblyInfo.cs file for your MyCode project, you can add the following

[assembly:InternalsVisibleTo("MyCode.Tests")

This does exactly what it says, it makes your internals visible inside the MyCode.Tests code base. For more info see InternalsVisibleTo and Friend assemblies

Upvotes: 1

Related Questions