【问题标题】:Finding difficulty in unit testing a Controller Action method using NUnit使用 NUnit 对 Controller Action 方法进行单元测试时遇到困难
【发布时间】:2012-10-06 06:56:31
【问题描述】:

我想使用 NUnit 测试框架对方法 ExecLogin() 进行单元测试。但是我在为测试编写代码时遇到了问题,因为 GenerateInput() 方法被声明为内部虚拟。因此,我无法将我认为需要的 SessionUserId 参数传递给它。请指导我如何为 ExecLogin() 编写单元测试代码。我是测试新手。

这与 ASP.NET MVC3 测试控制器操作有关。

    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) });
        }
    }

这是我们的模型类:

   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; }
   }

在学习依赖注入模式时,我了解到使用具体类可以使代码更紧密地耦合。代码耦合得越紧密,测试就越困难。这就是为什么我无法正确测试它的原因吗?请帮忙。

【问题讨论】:

  • 你展示的例子中有很多未知的方法:EncodingHelper.GetHashedPasswordSomeDelegate.Instance.ExecuteOperationJsonResponse&lt;T&gt;PopulateSessionGetClientIpAddress,...你不能对内部进行单元测试方法。您只需要对公共 ExecLogin 操作进行单元测试。但是为此,您必须设置所有依赖项。
  • 如何在测试方法中设置依赖关系?我必须遵循任何特定的结构吗?由于我是测试新手,请尽可能详细地维护
  • 你为什么用StringBuilder构建你的XML?
  • 对于 XML 元素的连接..因为我正在使用 Append() 方法。
  • @DarinDimitrov 您能否明确指导我如何尝试设置依赖项?请帮忙。

标签: c# asp.net-mvc-3 visual-studio-2010 unit-testing nunit


【解决方案1】:

这实际上是一种常见模式的一部分,如何在不干扰公开可用接口的情况下提供额外的测试挂钩点,幸运的是,内部是你的朋友。

我假设问题在于您有 2 个程序集,为简单起见,我们将它们称为 MyCode.dll 和 MyCode.Tests.dll。这意味着 MyCode.Tests 无法访问 MyCode 的内部方法,因为基本上它不是内部的 :-)

如果您转到 MyCode 项目的 AssemblyInfo.cs 文件,则可以添加以下内容

[assembly:InternalsVisibleTo("MyCode.Tests")

这正是它所说的,它使您的内部结构在 MyCode.Tests 代码库中可见。有关详细信息,请参阅 InternalsVisibleToFriend assemblies

【讨论】:

  • 是的,很好的建议。谢谢。但是,我在将 SessionUserId 传递给 GenerateInput() 方法时遇到问题
  • 我在 Visual NUnit 中有 NullReferenceException。但我认为这是我的错误产生的。您能否告诉我如何完成关于我的上述代码的单元测试?我是测试平台的新手。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-08
  • 2010-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多