我正在尝试测试使用以下域对象的方法。
public class PartyRoom
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int Capacity { get; set; }
public bool IsAvailable { get; set; }
public virtual ICollection<RoomBooking> Bookings { get; set; }
}
public class RoomBooking
{
public int Id { get; set; }
public BookingType BookingType { get; set; }
public int PartyRoomId { get; set; }
public int TimeSlotId { get; set; }
public DateTime Date { get; set; }
public virtual PartyRoom PartyRoom { get; set; }
public virtual TimeSlot TimeSlot { get; set; }
}
public enum BookingType
{
PartyOrder,
RoomRental,
Corporate
}
我有一个存储库模拟我正在设置像这样的房间预订:
_roomBookingRepositoryMock.Setup(x => x.Get()).Returns(roomBookings.AsQueryable);
返回的roomBookings
如下所示:
var roomBookings = new List<RoomBooking>
{
new RoomBooking()
{
Id = 1,
BookingType = BookingType.PartyOrder,
Date = new DateTime(2014, 11, 15),
PartyRoomId = 2,
TimeSlotId = 1
},
new RoomBooking()
{
Id = 2,
BookingType = BookingType.PartyOrder,
Date = new DateTime(2014, 11, 15),
PartyRoomId = 4,
TimeSlotId = 3
},
new RoomBooking()
{
Id = 3,
BookingType = BookingType.PartyOrder,
Date = new DateTime(2014, 11, 15),
PartyRoomId = 5,
TimeSlotId = 4
}
};
运行测试时发生的事情是public virtual ICollection<RoomBooking> Bookings { get; set; }
始终为空。我不确定如何设置该属性,因为我的roombookings列表没有被嘲笑,因此SetupGet
似乎不起作用?
当我运行测试时,我得到:
System.ArgumentNullException:值不能为空。
当单步执行时,该属性为null。我想我不能假设NUnit会像Entity Framework一样在代码中进行连接,但我很难知道如何访问它并设置属性。
*我尽可能多地发布了代码,由于项目原因我无法分享该方法,但我可以确认问题是该属性为null且未进行设置。
答案 0 :(得分:0)
当您使用Entity Framework时,它会在内存中创建一个从数据库中检索到的信息的对象图。部分原因是它将使用虚拟属性为您提取其他表中的信息。
当您编写单元测试时,您不想访问数据库,因此您通常会模拟您的数据访问权限,这是您在此处所做的,通过创建模拟库。您遇到的问题是,因为您没有访问Entity Framework类,所以它不会为您填充域对象。通过创建RoomBooking
列表,您已经完成了部分工作,但是您需要创建所有的被测系统所依赖的对象。
在基本级别,您只需更改创建roomBookings
的方式即可包含缺失的信息。这样的事情可以解决问题:
var roomBookings = new List<RoomBooking>();
roomBookings.Add(new RoomBooking()
{
Id = 1,
BookingType = BookingType.PartyOrder,
Date = new DateTime(2014, 11, 15),
PartyRoomId = 2,
TimeSlotId = 1,
PartyRoom = new PartyRoom {
Bookings = roomBookings
}
});
roomBookings.Add(new RoomBooking()
{
Id = 2,
BookingType = BookingType.PartyOrder,
Date = new DateTime(2014, 11, 15),
PartyRoomId = 4,
TimeSlotId = 3,
PartyRoom = new PartyRoom {
Bookings = roomBookings
}
});
roomBookings.Add(new RoomBooking()
{
Id = 3,
BookingType = BookingType.PartyOrder,
Date = new DateTime(2014, 11, 15),
PartyRoomId = 5,
TimeSlotId = 4,
PartyRoom = new PartyRoom {
Bookings = roomBookings
}
});
请注意,我为每个PartyRoom
创建了一个RoomBooking
条目,并指向我正在创建的列表。这可能不是正确的做法(您可能需要为每个RoomBooking
创建一个新的PartyRoom
列表,其中只包含该会议室的预订,但没有看到您的数据库,我猜不到)
基本上,您需要创建测试和受测试系统所依赖的所有对象。
还有Autofixture这样的框架可以帮助您创建测试对象,值得您考虑。