ASP.NET Core对Controller进行单元测试的完整步骤

单元测试对我们的代码质量非常重要。很多同学都会对业务逻辑或者工具方法写测试用例,但是往往忽略了对Controller层写单元测试。我所在的公司没见过一个对Controller写过测试的。今天来演示下如果对Controller进行单元测试。以下内容默认您对单元测试有所了解,比如如何mock一个接口。在这里多叨叨一句,面向接口的好处,除了能够快速的替换实现类(其实大部分接口不会有多个实现),最大的好处就是可以进行mock,可以进行单元测试。

测试Action

下面的Action非常简单,非常常见的一种代码。根据用户id去获取用户信息然后展示出来。下面看看如何对这个Action进行测试。

public class UserController : Controller { private readonly IUserService _userService; public UserController(IUserService userService) { _userService = userService; } public IActionResult UserInfo(string userId) { if (string.IsNullOrEmpty(userId)) { throw new ArgumentNullException(nameof(userId)); } var user = _userService.Get(userId); return View(user); } }

测试代码:

[TestMethod()] public void UserInfoTest() { var userService = new Mock<IUserService>(); userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User()); var ctrl = new UserController(userService.Object); //对空参数进行assert Assert.ThrowsException<ArgumentNullException>(() => { var result = ctrl.UserInfo(null); }); //对空参数进行assert Assert.ThrowsException<ArgumentNullException>(() => { var result = ctrl.UserInfo(""); }); var result = ctrl.UserInfo("1"); Assert.IsNotNull(result); Assert.IsInstanceOfType(result, typeof(ViewResult)); }

我们对一个Action进行测试主要的思路就是模拟各种入参,使测试代码能够到达所有的分支,并且Assert输出是否为空,是否为指定的类型等。

对ViewModel进行测试

我们编写Action的时候还会涉及ViewModel给视图传递数据,这部分也需要进行测试。修改测试用例,加入对ViewModel的测试代码:

[TestMethod()] public void UserInfoTest() { var userService = new Mock<IUserService>(); userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User() { Id = "x" }) ; var ctrl = new UserController(userService.Object); Assert.ThrowsException<ArgumentNullException>(() => { var result = ctrl.UserInfo(null); }); Assert.ThrowsException<ArgumentNullException>(() => { var result = ctrl.UserInfo(""); }); var result = ctrl.UserInfo("1"); Assert.IsNotNull(result); Assert.IsInstanceOfType(result, typeof(ViewResult)); //对viewModel进行assert var vr = result as ViewResult; Assert.IsNotNull(vr.Model); Assert.IsInstanceOfType(vr.Model, typeof(User)); var user = vr.Model as User; Assert.AreEqual("x", user.Id); }

对ViewData进行测试

我们编写Action的时候还会涉及ViewData给视图传递数据,这部分同样需要测试。修改Action代码,对ViewData进行赋值:

public IActionResult UserInfo(string userId) { if (string.IsNullOrEmpty(userId)) { throw new ArgumentNullException(nameof(userId)); } var user = _userService.Get(userId); ViewData["title"] = "user_info"; return View(user); }

修改测试用例,加入对ViewData的测试代码:

[TestMethod()] public void UserInfoTest() { var userService = new Mock<IUserService>(); userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User() { Id = "x" }) ; var ctrl = new UserController(userService.Object); Assert.ThrowsException<ArgumentNullException>(() => { var result = ctrl.UserInfo(null); }); Assert.ThrowsException<ArgumentNullException>(() => { var result = ctrl.UserInfo(""); }); var result = ctrl.UserInfo("1"); Assert.IsNotNull(result); Assert.IsInstanceOfType(result, typeof(ViewResult)); var vr = result as ViewResult; Assert.IsNotNull(vr.Model); Assert.IsInstanceOfType(vr.Model, typeof(User)); var user = vr.Model as User; Assert.AreEqual("x", user.Id); //对viewData进行assert Assert.IsTrue(vr.ViewData.ContainsKey("title")); var title = vr.ViewData["title"]; Assert.AreEqual("user_info", title); }

对ViewBag进行测试

因为ViewBag事实上是ViewData的dynamic类型的包装,所以Action代码不用改,可以直接对ViewBag进行测试:

[TestMethod()] public void UserInfoTest() { var userService = new Mock<IUserService>(); userService.Setup(s => s.Get(It.IsAny<string>())).Returns(new User() { Id = "x" }) ; var ctrl = new UserController(userService.Object); Assert.ThrowsException<ArgumentNullException>(() => { var result = ctrl.UserInfo(null); }); Assert.ThrowsException<ArgumentNullException>(() => { var result = ctrl.UserInfo(""); }); var result = ctrl.UserInfo("1"); Assert.IsNotNull(result); Assert.IsInstanceOfType(result, typeof(ViewResult)); var vr = result as ViewResult; Assert.IsNotNull(vr.Model); Assert.IsInstanceOfType(vr.Model, typeof(User)); var user = vr.Model as User; Assert.AreEqual("x", user.Id); Assert.IsTrue(vr.ViewData.ContainsKey("title")); var title = vr.ViewData["title"]; Assert.AreEqual("user_info", title); //对viewBag进行assert string title1 = ctrl.ViewBag.title; Assert.AreEqual("user_info", title1); }

设置HttpContext

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/923f9f22afd697ee057bb9897e41e408.html