如何在单元测试控制器最小起订量上下文中跳过调用函数?
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 容器中,以便在系统 运行 生产时将实际实现正确注入控制器。
这是我的控制器
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 容器中,以便在系统 运行 生产时将实际实现正确注入控制器。