1.控制器测试

注意点:

1.控制器中不要包含业务逻辑

2.通过构造函数传递服务依赖

例:MathController中有一个Add的Action

using FirstUnitTest.Services;
using System.Web.Mvc; namespace FirstUnitTest.Controllers
{
public class MathController : Controller
{
IMathService _service; public MathController(IMathService service) {
_service = service;
} // GET: Math
public RedirectToRouteResult Index()
{
return RedirectToAction("Add");
//return View();
} [HttpGet]
public ActionResult Add()
{
return View();
} [HttpPost]
public ViewResult Add(int left, int right)
{
ViewBag.Result = _service.Add(left, right);
return View();
}
}
}

IMathService定义如下,很显然是个求和方法:

namespace FirstUnitTest.Services
{
public interface IMathService
{
int Add(int left, int right);
}
}

编写一个假Service,给Controller提供一个假的业务逻辑层。

using FirstUnitTest.Services;

namespace FirstUnitTest.Tests.Services
{
public class SpyMathService : IMathService
{
public int Add_Left;
public int Add_Right;
public int Add_Result; public int Add(int left, int right)
{
Add_Left = left;
Add_Right = right; return Add_Result;
}
}
}

注意:上面的SpyService中没有对两个值求和,因为我们只关注MathService的Input和Output(Input就是left和right参数,Output就是返回值)。

测试方法:

[TestMethod]
public void AddUseMathService()
{
SpyMathService service = new SpyMathService() { Add_Result = 42 };
MathController controller = new MathController(service);
ViewResult result = controller.Add(4, 12); Assert.AreEqual(service.Add_Result, result.ViewBag.Result);
Assert.AreEqual(4, service.Add_Left);
Assert.AreEqual(12, service.Add_Right);
}

Redirect测试(上面MathController中的Index Action):

[TestMethod]
public void RedirectToAdd()
{
SpyMathService service = new SpyMathService();
MathController controller = new MathController(service); RedirectToRouteResult result = controller.Index(); Assert.AreEqual("Add", result.RouteValues["action"]);
}

2.路由测试

默认MVC项目的路由如下:

using System.Web.Mvc;
using System.Web.Routing; namespace FirstUnitTest
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}

测试方法:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing; namespace FirstUnitTest.Tests.Routes
{
[TestClass]
public class RouteTest
{
/// <summary>
/// 测试IngoreRoute函数调用
/// </summary>
[TestMethod]
public void RouteForEmbeddedResource()
{
// Arrange
var mockContext = new Mock<HttpContextBase>();
mockContext.Setup(c => c.Request.AppRelativeCurrentExecutionFilePath)
.Returns("~/handler.axd");
var routes = new RouteCollection();
//MvcApplication.RegisterRoutes(routes);
RouteConfig.RegisterRoutes(routes); // Act
RouteData routeData = routes.GetRouteData(mockContext.Object); // Assert
Assert.IsNotNull(routeData);
Assert.IsInstanceOfType(routeData.RouteHandler, typeof(StopRoutingHandler));
} /// <summary>
/// 测试MapRoute函数调用
/// </summary>
[TestMethod]
public void RouteToHomePae()
{
// Arrange
var mockContext = new Mock<HttpContextBase>();
mockContext.Setup(c => c.Request.AppRelativeCurrentExecutionFilePath)
.Returns("~/");
var routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes); // Act
RouteData routeData = routes.GetRouteData(mockContext.Object); // Assert
Assert.IsNotNull(routeData);
Assert.AreEqual("Home", routeData.Values["controller"]);
Assert.AreEqual("Index", routeData.Values["action"]);
Assert.AreEqual(UrlParameter.Optional, routeData.Values["id"]);
} // 不需要对不匹配路由编写测试代码
}
}

使用Mock需要安装Moq包(需要设定ProjectName参数,否则会默认安装到Web工程)

Install-Package moq -ProjectName FirstUnitTest.Tests

3.验证测试

Movie模型:

using System.ComponentModel.DataAnnotations;
using System.Data.Entity; namespace FirstUnitTest.Models
{
public class Movie
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
[Range(1920, 2015)]
public int ReleaseYear { get; set; }
public int RunTime { get; set; }
} public class MovieDb : DbContext
{
public DbSet<Movie> Movies { get; set; }
}
}

属性验证:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FirstUnitTest.Models;
using System.ComponentModel.DataAnnotations; namespace FirstUnitTest.Tests.Validation
{
[TestClass]
public class MovieValidationTest
{
[TestMethod]
public void TitleRequireTest()
{
System.Threading.Thread.CurrentThread.CurrentUICulture
= new System.Globalization.CultureInfo("zh-cn");
Movie movie = new Movie();
ValidationContext context = new ValidationContext(movie, null, null) {
DisplayName = "Title",
MemberName = "Title",
};
RequiredAttribute validator = new RequiredAttribute(); try
{
validator.Validate(movie.Title, context);
}
catch (ValidationException ex)
{
// 错误消息的语言由当前线程的CurrentUICulture决定
Assert.AreEqual("Title 字段是必需的。", ex.Message);
//throw;
}
}
}
}

※本文参照《ASP.NET MVC 5高级编程(第5版)》

【MVC5】First Unit Test的更多相关文章

  1. 【MVC5】画面多按钮提交

    画面上有个多个按钮时,如何绑定到各自的Action上? 1.追加如下MultipleButtonAttribute类 1 using System; 2 using System.Reflection ...

  2. 【MVC5】对MySql数据库使用EntityFramework

    版本: MySql : 5.6.3 MySql.Data : 6.9.7 MVC : 5 EntityFramework : 6.1.3 VS : 2015 步骤: 1.安装[mysql-connec ...

  3. 【MVC5】使用域用户登录+记住我

    1.配置Web.config文件 添加域链接字符串 <connectionStrings> <add name="ADConnectionString" conn ...

  4. 【MVC5】使用权限+角色

    1.在Ticket中设置用户角色 在权限的Ticket中设置用户的角色(这里是逗号分割). List<string> roles = new List<string>(); i ...

  5. 【MVC5】后台修改的Model值反映不到客户端的问题

    画面上的检索结果有翻页功能,就在画面上追加了几个隐藏控件保存上次检索时的检索条件. 检索时更新这些隐藏控件的值,Debug时确实把Model中对应的属性值变掉了,但是到了客户端又变回之前的值了. 百思 ...

  6. 【MVC5】日期选择控件DatePicker

    项目中使用了Bootstrap,日期控件就选择了依赖于bootstrap的DatePicker. 在App_Start\BundleConfig.cs中引用css和js文件: bundles.Add( ...

  7. 【MVC5】First AngularJS

    ※本文参照<ASP.NET MVC 5高级编程(第5版)> 1.创建Web工程 1-1.选择ASP.NET Web Application→Web API 工程名为[atTheMovie] ...

  8. 【t033】单位unit

    Time Limit: 1 second Memory Limit: 64 MB [问题描述] 某星球上有很多计量系统,之间的计量单位的转换很繁琐.希望你能编程解决这个问题. 现有N (1 <= ...

  9. 【MVC5】ASP.NET MVC 项目笔记汇总

    ASP.NET MVC 5 + EntityFramework 6 + MySql 先写下列表,之后慢慢补上~ 对MySql数据库使用EntityFramework 使用域用户登录+记住我 画面多按钮 ...

随机推荐

  1. Duplicate the UIButton and Move it

    http://stackoverflow.com/questions/19241208/duplicate-the-uibutton-and-move-it/26438692#26438692 1do ...

  2. (十一)Ubuntu下面怎么找到一个软件安装的目录,卸载软件

    aptitude show packagename 实例: aptitude show sublime-text-installer 可以看到这个软件一系列信息 dpkg命令 dpkg -l //列车 ...

  3. PHP获取IP的方法

    function getIP() { if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $realip = $_SERVER['HTTP_X_FORWARD ...

  4. [BZOJ1191][HNOI2006]超级英雄Hero 类似二分图的最大匹配

    1191: [HNOI2006]超级英雄Hero Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4740  Solved: 2162[Submit][ ...

  5. MVC5下的switchbutton

    最近想提高代码生成的时候,是否选择显示样式好看些,所以想到了SwitchButton. 但是碰到个问题是,添加页面的这个初始值,需要写成true或者false 包括修改页面做个判断的话,渲染的做法也是 ...

  6. JDK7集合框架源码阅读(五) Hashtable

    基于版本jdk1.7.0_80 java.util.Hashtable 代码如下 /* * Copyright (c) 1994, 2011, Oracle and/or its affiliates ...

  7. HDU 6351暴力枚举 6354计算几何

    Beautiful Now Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)T ...

  8. UVA 624 CD【01背包+路径记录】

    You have a long drive by car ahead. You have a tape recorder, but unfortunately your best music is o ...

  9. 服务的注册与发现Eureka(二)

    1.服务治理概念 在传统rpc远程调用中,服务与服务依赖关系,管理比较复杂,所以需要使用服务治理,管理服务与服务之间依赖关系,可以实现服务调用.负载均衡.容错等,实现服务发现与注册. 2.服务的注册与 ...

  10. #423 Div2 D

    #423 Div2 D 题意 构造一个 n 个节点的树,恰好有 k 个叶子节点 (叶子节点的定义是只与树上的某一个节点存在连边),要求任意两个叶子节点的距离的最大值最小,距离为两个节点间边的数量,输出 ...