【问题标题】:Nunit setup virtual property on repository mockNunit 在存储库模拟上设置虚拟属性
【发布时间】:2014-09-04 02:23:36
【问题描述】:

我正在尝试测试使用以下域对象的方法。

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&lt;RoomBooking&gt; Bookings { get; set; } 始终为空。我不确定如何设置该属性,因为我的房间预订列表没有被模拟,所以SetupGet 似乎不起作用?

当我运行测试时,我得到:

System.ArgumentNullException : 值不能为空。

单步执行时显示属性为空。我想我不能假设 NUnit 会像 Entity Framework 首先在代码中那样连接它,但我很难理解如何访问它并设置属性。

*我尽可能多地发布了代码,由于项目原因我无法共享方法本身,但我可以确认问题是属性为空且未设置。

【问题讨论】:

  • '当我运行测试时发生了什么......' 你能把你的测试也发布吗?
  • 您所说的Bookings 属性似乎是PartyRoom 类的一部分,但您从未在代码中使用它。此外,当您创建PartyRoom 的实例时,如果您从不更改它,请确保Bookingsnull。你期望发生什么?抱歉,我不清楚。
  • Bookings 作为虚拟属性链接到 roomBookingsRepository,并且在正常运行时拉入链接到派对房间 ID 的预订。这是EF中的一对多关系。我想我可能需要模拟我的 DBSet 来测试它。

标签: c# unit-testing mocking nunit moq


【解决方案1】:

当您使用实体框架时,它会在内存中创建一个对象图,用于存储从数据库中检索到的信息。部分原因是它将使用虚拟属性为您从其他表中获取信息。

在编写单元测试时,您不想访问数据库,因此您通常通过创建存储库的模拟来模拟您在此处所做的数据访问。您遇到的问题是,因为您没有使用实体框架类,它不会为您填充域对象。通过创建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
    }
});

请注意,我正在为每个 RoomBooking 创建一个 PartyRoom 条目并指向我正在创建的列表。这可能不是正确的做法(您可能需要为每个 PartyRoom 创建一个新的 RoomBooking 列表,该列表仅包含该房间的预订,但没有看到您的数据库,我猜)。

基本上,您需要创建您的测试和被测系统所依赖的所有对象。

还有诸如 Autofixture 之类的框架可以帮助您创建测试对象,这可能值得您考虑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多