2

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.

9
  • 2
    There are lots of unknown methods in the example you have shown: EncodingHelper.GetHashedPassword, SomeDelegate.Instance.ExecuteOperation, JsonResponse<T>, PopulateSession, GetClientIpAddress, ... You cannot unit test the internal methods. You need to unit test only the public ExecLogin action. But for this you will have to setup all the dependencies. Commented Oct 16, 2012 at 8:18
  • how can i setup dependencies in a testing method? is there any particular structure i have to follow? please maintain as details as possible as i am new to testing Commented Oct 16, 2012 at 8:30
  • 1
    Why do you build your XML with a StringBuilder? Commented Oct 16, 2012 at 8:30
  • For the concatenation of XML elements..as I'm using the Append() method. Commented Oct 16, 2012 at 8:41
  • @DarinDimitrov Would you explicitly guide me how can I try to setup the dependencies? Please help. Commented Oct 18, 2012 at 10:15

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

2 Comments

yes, nice suggestion. thank you. but, I'm having problem in passing SessionUserId to the GenerateInput() method
I'm having NullReferenceException in Visual NUnit. But that I think is generated from my mistake. Could you please show me how the unit test regarding my above code can be done? I'm new to testing platform.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.