无涯教程-ASP.NET MVC - 单元测试

51 阅读5分钟

在计算机编程中,单元测试是一种软件测试方法,通过该方法可以测试源代码的各个单元以确定它们是否适合使用。换句话说,这是一个软件开发过程,其中应用程序的最小可测试部分(称为单元)被单独且独立地检查以确保其正常运行。

单元测试通常是自动化的,但也可以手动完成。

单元测试的目标

单元测试的主要目标是采用应用程序中最小的可测试软件,并确定其行为是否完全符合您的预期。在将每个单元集成到模块中以测试模块之间的接口之前,需要分别测试每个单元。

让我们看一个简单的单元测试示例,在该示例中,我们使用单元测试创​​建了一个新的ASP.NET MVC应用程序。

步骤1 - 打开Visual Studio,然后单击File→New→Item菜单选项。

将打开一个"New Project"对话框。

New Project Dialog

步骤2 - 在左窗格中,选择 Templates > Visual C# > Web.

步骤3 - 在中间窗格中,选择ASP.NET Web应用程序。

步骤4 - 在"Name"字段中输入项目名称" MVCUnitTestingDemo",然后单击"OK"继续。您将看到以下对话框,要求您设置ASP.NET项目的初始内容。

MVCUnitTestingDemo

步骤5 - 选择MVC作为模板,不要忘记选中对话框底部的"Add unit tests"复选框。

通过Visual Studio创建项目后,您将在"Solution Explorer"窗口中看到许多文件和文件夹。

步骤6 - 您可以看到Solution Explorer中有两个项目。一个是ASP.NET Web项目,另一个是单元测试项目。

Web Project

步骤7 - 运行此应用程序,您将看到以下输出。

Run Web Project

如上面的屏幕截图所示,导航栏上有"Home","About"和"Contact"按钮。选择"About",您将看到以下视图。

About Select

选择"Contact",然后弹出以下屏幕。

Contact Select

现在,我们扩展" MVCUnitTestingDemo"项目,您将在Controllers文件夹下看到HomeController.cs文件。

HomeController.cs file

HomeController包含三种操作方法,如以下代码所示。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web; using System.Web.Mvc;

namespace MVCUnitTestingDemo.Controllers { public class HomeController : Controller{ public ActionResult Index(){ return View(); }

  </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">ActionResult</span><span class="pln"> </span><span class="typ">About</span><span class="pun">(){</span><span class="pln">
     </span><span class="typ">ViewBag</span><span class="pun">.</span><span class="typ">Message</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Your application description page."</span><span class="pun">;</span><span class="pln">
     </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">View</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
	
  </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">ActionResult</span><span class="pln"> </span><span class="typ">Contact</span><span class="pun">(){</span><span class="pln">
     </span><span class="typ">ViewBag</span><span class="pun">.</span><span class="typ">Message</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Your contact page."</span><span class="pun">;</span><span class="pln">
     </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">View</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} }

让我们展开 MVCUnitTestingDemo.Tests 项目,您将在Controllers文件夹下看到HomeControllerTest.cs文件。

MVCUnitTestingDemo.Test

在这个HomeControllerTest类中,您将看到三个方法,如以下代码所示。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Web.Mvc; using Microsoft.VisualStudio.TestTools.UnitTesting;

using MVCUnitTestingDemo; using MVCUnitTestingDemo.Controllers;

namespace MVCUnitTestingDemo.Tests.Controllers{ [TestClass] public class HomeControllerTest{

  </span><span class="pun">[</span><span class="typ">TestMethod</span><span class="pun">]</span><span class="pln">
  </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Index</span><span class="pun">(){</span><span class="pln">
     </span><span class="com">//Arrange</span><span class="pln">
     </span><span class="typ">HomeController</span><span class="pln"> controller </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HomeController</span><span class="pun">();</span><span class="pln">
     </span><span class="com">//Act</span><span class="pln">
     </span><span class="typ">ViewResult</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> controller</span><span class="pun">.</span><span class="typ">Index</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> </span><span class="typ">ViewResult</span><span class="pun">;</span><span class="pln">
     </span><span class="com">//Assert</span><span class="pln">
     </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">IsNotNull</span><span class="pun">(</span><span class="pln">result</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
	
  </span><span class="pun">[</span><span class="typ">TestMethod</span><span class="pun">]</span><span class="pln">
  </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">About</span><span class="pun">(){</span><span class="pln">
     </span><span class="com">//Arrange</span><span class="pln">
     </span><span class="typ">HomeController</span><span class="pln"> controller </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HomeController</span><span class="pun">();</span><span class="pln">
     </span><span class="com">//Act</span><span class="pln">
     </span><span class="typ">ViewResult</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> controller</span><span class="pun">.</span><span class="typ">About</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> </span><span class="typ">ViewResult</span><span class="pun">;</span><span class="pln">
     </span><span class="com">//Assert</span><span class="pln">
     </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">AreEqual</span><span class="pun">(</span><span class="str">"Your application description page."</span><span class="pun">,</span><span class="pln"> result</span><span class="pun">.</span><span class="typ">ViewBag</span><span class="pun">.</span><span class="typ">Message</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
	
  </span><span class="pun">[</span><span class="typ">TestMethod</span><span class="pun">]</span><span class="pln">
  </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Contact</span><span class="pun">(){</span><span class="pln">
     </span><span class="com">//Arrange</span><span class="pln">
     </span><span class="typ">HomeController</span><span class="pln"> controller </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HomeController</span><span class="pun">();</span><span class="pln">
     </span><span class="com">//Act</span><span class="pln">
     </span><span class="typ">ViewResult</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> controller</span><span class="pun">.</span><span class="typ">Contact</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> </span><span class="typ">ViewResult</span><span class="pun">;</span><span class="pln">
     </span><span class="com">//Assert</span><span class="pln">
     </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">IsNotNull</span><span class="pun">(</span><span class="pln">result</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} }

这三种方法将测试"About"和"Contact"操作方法是否正常工作。要测试这三种操作方法,请转到"Test"菜单。

Test Menu

选择Run→All Tests to test 这些操作方法。

Action Methods

现在,您将在左侧看到"Test Explorer",您可以在其中看到所有测试均已通过,让我们添加另一种操作方法,该方法将列出所有员工。首先,我们需要在Models文件夹中添加一个employee类。

以下是Employee类的实现。

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;

namespace MVCUnitTestingDemo.Models{ public class Employee{ public int ID { get; set; } public string Name { get; set; } public DateTime JoiningDate { get; set; } public int Age { get; set; } } }

我们需要添加EmployeeController。右键单击Solution Explorer中的controller文件夹,然后选择Add→Controller。

它将显示"Add Scaffold"对话框。

Add Scaffold

选择" MVC 5 Controller–Empty"选项,然后单击"Add"按钮,将出现"Add Controller"对话框。

将名称设置为EmployeeController,然后单击"Add"按钮。

Add Controller EmployeeController

您将在Controllers文件夹中看到一个新的C#文件" EmployeeController.cs",该文件已打开,可以在Visual Studio中进行编辑。让我们使用以下代码更新EmployeeController。

using MVCUnitTestingDemo.Models;
using System;
using System.Collections.Generic;
using System.Linq;

using System.Web; using System.Web.Mvc;

namespace MVCUnitTestingDemo.Controllers { public class EmployeeController : Controller{ [NonAction]

  </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">List</span><span class="pun">&lt;</span><span class="typ">Employee</span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">GetEmployeeList</span><span class="pun">(){</span><span class="pln">
     </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">List</span><span class="pun">&lt;</span><span class="typ">Employee</span><span class="pun">&gt;{</span><span class="pln">
        </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">{</span><span class="pln">
           ID </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
           </span><span class="typ">Name</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Allan"</span><span class="pun">,</span><span class="pln">
           </span><span class="typ">JoiningDate</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Parse</span><span class="pun">(</span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Today</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">()),</span><span class="pln">
           </span><span class="typ">Age</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">23</span><span class="pln">
        </span><span class="pun">},</span><span class="pln">
			
        </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">{</span><span class="pln">
           ID </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln">
           </span><span class="typ">Name</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Carson"</span><span class="pun">,</span><span class="pln">
           </span><span class="typ">JoiningDate</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Parse</span><span class="pun">(</span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Today</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">()),</span><span class="pln">
           </span><span class="typ">Age</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">45</span><span class="pln">
        </span><span class="pun">},</span><span class="pln">
			
        </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">{</span><span class="pln">
           ID </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln">
           </span><span class="typ">Name</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Carson"</span><span class="pun">,</span><span class="pln">
           </span><span class="typ">JoiningDate</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Parse</span><span class="pun">(</span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Today</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">()),</span><span class="pln">
           </span><span class="typ">Age</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">37</span><span class="pln">
        </span><span class="pun">},</span><span class="pln">
			
        </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Employee</span><span class="pun">{</span><span class="pln">
           ID </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln">
           </span><span class="typ">Name</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Laura"</span><span class="pun">,</span><span class="pln">
           </span><span class="typ">JoiningDate</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Parse</span><span class="pun">(</span><span class="typ">DateTime</span><span class="pun">.</span><span class="typ">Today</span><span class="pun">.</span><span class="typ">ToString</span><span class="pun">()),</span><span class="pln">
           </span><span class="typ">Age</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">26</span><span class="pln">
        </span><span class="pun">},</span><span class="pln">
     </span><span class="pun">};</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  
  </span><span class="com">//GET: Employee</span><span class="pln">
  </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">ActionResult</span><span class="pln"> </span><span class="typ">Index</span><span class="pun">(){</span><span class="pln">
     </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">View</span><span class="pun">();</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
	
  </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">ActionResult</span><span class="pln"> </span><span class="typ">Employees</span><span class="pun">(){</span><span class="pln">
     </span><span class="kwd">var</span><span class="pln"> employees </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> e </span><span class="kwd">in</span><span class="pln"> </span><span class="typ">GetEmployeeList</span><span class="pun">()</span><span class="pln">
     </span><span class="kwd">orderby</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">ID
     </span><span class="kwd">select</span><span class="pln"> e</span><span class="pun">;</span><span class="pln">
     </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">View</span><span class="pun">(</span><span class="pln">employees</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">

} }

要添加"Employees View"操作方法,请右键单击"Employees"操作,然后选择"Add View…"。

Employee Action

您将看到默认的视图名称。从模板下拉列表中选择"List",从模型类下拉列表中选择"Employee",然后单击确定。

现在,我们需要添加链接"Employees"列表,让我们打开"Views/Shared"文件夹下的_layout.cshtml文件,然后在"Contact"链接下方添加"employees"链接。

<li>@Html.ActionLink("Employees List", "Employees", "Employee")</li>

以下是_layout.cshtml的完整实现。

<!DOCTYPE html>
<html>
   <head>
      <meta charset = "utf-8" />
      <meta name = "viewport" content = "width=device-width, initial-scale=1.0">
      <title>@ViewBag.Title - My ASP.NET Application</title>
      @Styles.Render("~/Content/css")
      @Scripts.Render("~/bundles/modernizr")
   </head>

<body> <div class = "navbar navbar-inverse navbar-fixed-top"> <div class = "container">

        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="atv">"navbar-header"</span><span class="tag">&gt;</span><span class="pln">
           </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="atv">"button"</span><span class="pln"> </span><span class="atn">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="atv">"navbar-toggle"</span><span class="pln"> </span><span class="atn">datatoggle</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
              </span><span class="atv">"collapse"</span><span class="pln"> </span><span class="atn">data-target</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="atv">".navbar-collapse"</span><span class="tag">&gt;</span><span class="pln">
              </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="atv">"icon-bar"</span><span class="tag">&gt;&lt;/span&gt;</span><span class="pln">
              </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="atv">"icon-bar"</span><span class="tag">&gt;&lt;/span&gt;</span><span class="pln">
              </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="atv">"icon-bar"</span><span class="tag">&gt;&lt;/span&gt;</span><span class="pln">
           </span><span class="tag">&lt;/button&gt;</span><span class="pln">
				
           @Html.ActionLink("Application name", "Index", "Home", new
              { area="" }, new { @class="navbar-brand" })
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
			
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="atv">"navbar-collapse collapse"</span><span class="tag">&gt;</span><span class="pln">
           </span><span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="atv">"nav navbar-nav"</span><span class="tag">&gt;</span><span class="pln">
              </span><span class="tag">&lt;li&gt;</span><span class="pln">@Html.ActionLink("Home", "Index", "Home")</span><span class="tag">&lt;/li&gt;</span><span class="pln">
              </span><span class="tag">&lt;li&gt;</span><span class="pln">@Html.ActionLink("About", "About", "Home")</span><span class="tag">&lt;/li&gt;</span><span class="pln">
              </span><span class="tag">&lt;li&gt;</span><span class="pln">@Html.ActionLink("Contact", "Contact", "Home")</span><span class="tag">&lt;/li&gt;</span><span class="pln">
              </span><span class="tag">&lt;li&gt;</span><span class="pln">@Html.ActionLink("Employees List", "Employees", "Employee")</span><span class="tag">&lt;/li&gt;</span><span class="pln">
           </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
				
           @Html.Partial("_LoginPartial")
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
			
     </span><span class="tag">&lt;/div&gt;</span><span class="pln">
		
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">
	
  </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="atv">"container body-content"</span><span class="tag">&gt;</span><span class="pln">
     @RenderBody()
     </span><span class="tag">&lt;hr</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
     </span><span class="tag">&lt;footer&gt;</span><span class="pln">
        </span><span class="tag">&lt;p&gt;</span><span class="pln">© @DateTime.Now.Year - My ASP.NET Application</span><span class="tag">&lt;/p&gt;</span><span class="pln">
     </span><span class="tag">&lt;/footer&gt;</span><span class="pln">
  </span><span class="tag">&lt;/div&gt;</span><span class="pln">
	
  @Scripts.Render("~/bundles/jquery")
  @Scripts.Render("~/bundles/bootstrap")
  @RenderSection("scripts", required: false)
	

</body> </html>

要从Employee控制器测试Employees操作方法,我们需要在单元测试项目中添加另一种测试方法。在EmployeeControllerTest类之后,我们将在其中测试Employees操作方法。

[TestClass]
public class EmployeeControllerTest{
   [TestMethod]
   public void Employees(){
      //Arrange
      EmployeeController controller = new EmployeeController();
  </span><span class="com">//Act</span><span class="pln">
  </span><span class="typ">ViewResult</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> controller</span><span class="pun">.</span><span class="typ">Index</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> </span><span class="typ">ViewResult</span><span class="pun">;</span><span class="pln">
	
  </span><span class="com">//Assert</span><span class="pln">
  </span><span class="typ">Assert</span><span class="pun">.</span><span class="typ">IsNotNull</span><span class="pun">(</span><span class="pln">result</span><span class="pun">);</span><span class="pln">

} }

从"Test"菜单中选择"Run"→"All Tests"以测试这些操作方法。

Employee Test Method

您可以看到Employees测试方法现在也已通过。运行应用程序时,将看到以下输出。

点击导航栏中的"Employees List"选项,您将看到员工列表。

Employee List

参考链接

www.learnfk.com/asp.net_mvc…