如何在单元测试控制器最小起订量上下文中跳过调用函数?

How to skip calling function in unit testing controller moq context?

这是我的控制器

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 容器中,以便在系统 运行 生产时将实际实现正确注入控制器。