c# - 如何在单元测试控制器 moq 上下文中跳过调用函数?
问题描述
这是我的控制器
BusinessLayer.Lookup.Lookup_Rooms RoomsBL = new BusinessLayer.Lookup.Lookup_Rooms();
[HttpPost]
public ActionResult CreateRoom(UMIS_Portal_BackEnd.Areas.StudentAcadimic.Models.RoomLocationModel room) {
if (ModelState.IsValid)
{
try
{
// TODO: Add insert logic here
int? Serial = RoomsBL.Lookup_RoomInsert(room.BuildingFloorID, room.RoomName, room.Min_Capacity, room.Max_Capacity);
}
catch (Exception error)
{
ViewBag.Messages = error.InnerException.Message;
}
}
return View();
}
我只想测试此操作结果是否存在视图,因此我编写了此代码
[TestMethod()]
public void CreateRoomTestPost()
{
LookupRoomsController controller = new LookupRoomsController();
UMIS_Portal_BackEnd.Areas.StudentAcadimic.Models.RoomLocationModel room = new UMIS_Portal_BackEnd.Areas.StudentAcadimic.Models.RoomLocationModel();
ViewResult viewResult = controller.CreateRoom(room) as ViewResult;
Assert.IsNotNull(viewResult);
}
我希望测试跳过调用
int? Serial = RoomsBL.Lookup_RoomInsert(room.BuildingFloorID, room.RoomName, room.Min_Capacity, room.Max_Capacity);
在主控制器动作上。
解决方案
问题是控制器与实现细节紧密耦合
BusinessLayer.Lookup.Lookup_Rooms RoomsBL = new BusinessLayer.Lookup.Lookup_Rooms();
而不是将抽象显式注入其中。创建其依赖关系不是控制器的责任。(单一职责原则 (SRP) 和关注点分离 (Soc))
Lookup_Rooms
需要抽象
public interface ILookup_Rooms {
//...
}
public class Lookup_Rooms : ILookup_Rooms {
//...
}
并将抽象显式注入控制器。
private readonly BusinessLayer.Lookup.ILookup_Rooms RoomsBL;
//CTOR
public LookupRoomsController(ILookup_Rooms RoomsBL) {
this.RoomsBL = RoomsBL;
}
[HttpPost]
public ActionResult CreateRoom(RoomLocationModel room) {
if (ModelState.IsValid) {
try {
// TODO: Add insert logic here
int? Serial = RoomsBL.Lookup_RoomInsert(room.BuildingFloorID, room.RoomName, room.Min_Capacity, room.Max_Capacity);
} catch (Exception error) {
ViewBag.Messages = error.InnerException.Message;
}
}
return View();
}
这样,当Lookup_RoomInsert
在隔离单元测试中调用时,可以使模拟的不执行任何操作。
[TestMethod()]
public void CreateRoomTestPost() {
// Arrange
ILookup_Rooms mock = Mock.Of<ILookup_Rooms>(); //using MOQ
LookupRoomsController controller = new LookupRoomsController(mock);
RoomLocationModel room = new RoomLocationModel();
// Act
ViewResult viewResult = controller.CreateRoom(room) as ViewResult;
// Assert
Assert.IsNotNull(viewResult);
}
最后,抽象和实现应该注册到一个 DI 容器中,这样当系统在生产中运行时,实际的实现可以正确地注入到控制器中。
推荐阅读
- hsqldb - 为什么在嵌入式 HSQLDB 上运行更新查询会消耗大量内存?
- java - 如何在 Keycloak (3.4.3) 中的自定义 spnego Authenticator 中将自定义错误消息返回到前端?
- tfs - 2 个 TFS 应用程序层之间的通信
- import - Odoo 中的计划导入
- android - Android - 获取当前位置不起作用
- if-statement - 导入范围,但不包括日期且仅选择某个国家/地区
- c# - 从 C++ 转换的 C# 代码不起作用
- java - Prometheus 中的 apache Beam 缺少指标
- layout - Plotly:仅在特定子图中堆积条形图
- gitlab - GitLab CI 预定义的环境变量仅在子句中不被识别?