如何在单元测试控制器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容器中,这样当系统在生产中运行时,实际实现就可以正确地注入控制器中。

最新更新