您的位置:首页 > 其它

【MVC5】First Unit Test

2015-11-09 14:52 387 查看

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版)》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: