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. 2018超详细sublime text3+python3.x安装配置教程(附常用插件安装教程)

    导读 本文是关于2018年7月最新版sublime text3+pythin3.x下载及安装配置教程,sublime text3版本为3176,python版本为3.7,安装环境是基于windows1 ...

  2. 校内训练0602 习题exercise

    [题目大意] f(i)=((Af(i-1)+B)/(Cf(i-1)+D)) mod P. 给出f(0), A, B, C, D, P, n,求f(n). 多组数据T<=1e4 n<=1e1 ...

  3. 汕头市队赛 SRM1X T2 ——扫描线

    绵津见-终 SRM 13 背景 “西瓜也是可以种在海上的!”——绵津见 然而种在海上的西瓜最需要防范的,是时不时会涌向瓜田的阵阵海浪. 幸好,身为海神的绵津见可以释放魔法“水平如镜”来阻止海浪拍打西瓜 ...

  4. [bzoj2726][SDOI2012]任务安排 ——斜率优化,动态规划,二分,代价提前计算

    题解 本题的状态很容易设计: f[i] 为到第i个物件的最小代价. 但是方程不容易设计,因为有"后效性" 有两种方法解决: 1)倒过来设计动态规划,典型的,可以设计这样的方程: d ...

  5. .net 实用功能

    c#的DateTime.Now函数详解 [C#]Color颜色对照表 Sql日期时间格式转换 关于asp.net中页面事件加载的先后顺序 asp.net在ie7中使用FileUpload上传前预览图片 ...

  6. 中矿大 C 石头剪刀布【决策DP*待看/codeforces原题】

    时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32768K,其他语言65536K64bit IO Format: %lld 题目描述 齐齐和司机正在玩剪刀石头布,不过他俩有些玩腻了,所 ...

  7. Tomcat配置连接池

    Tomcat配置DBCP连接池 配置tomcat服务器的时候,使用到jndi;通过Context配置文件实现配置池对象,通过new initialConext()对象的lookup()获取到数据池对象 ...

  8. Dfs+Spfa【p1606】[USACO07FEB]荷叶塘Lilypad Pond

    Description 为了让奶牛们娱乐和锻炼,农夫约翰建造了一个美丽的池塘.这个长方形的池子被分成了M行N列个方格(1≤M,N≤30).一些格子是坚固得令人惊讶的莲花,还有一些格子是岩石,其余的只是 ...

  9. kibana-Coordinate Map

    1. Visualize 添加图形 2. 选择图形类型  Coordinate Map 3. 选择索引 4. 设定成图的聚合字段 如果有数据,点击右上角的三角形,地图上就会有显示. 5. 保存图形

  10. [BZOJ1038][ZJOI2008]瞭望塔(半平面交)

    1038: [ZJOI2008]瞭望塔 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2999  Solved: 1227[Submit][Statu ...