2014-09-04 64 views
1

我想測試一個使用下列域對象的方法。Nunit在存儲庫模擬上設置虛擬屬性

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; }始終爲空。我不知道如何設置這個屬性,因爲我的房間預定列表沒有被模擬,所以SetupGet似乎不起作用?

當我運行測試,我得到:

System.ArgumentNullException:值不能爲空。

哪些在逐步顯示時顯示屬性爲空。我想我不能假設NUnit會像Entity Framework那樣在代碼中將它連接起來,但我很難理解如何訪問它並設置屬性。

*我發佈儘可能多的代碼,方法本身我不能共享項目的原因,但我可以確認的問題是該屬性爲空,並沒有得到設置。

+0

'我運行測試時發生了什麼......'您能否發佈您的測試? – dee 2014-09-04 08:25:29

+0

似乎您所談論的「預訂」屬性是「PartyRoom」類的一部分,但您從不在代碼中使用它。另外,當你創建'PartyRoom'實例時,如果你永遠不改變它,肯定'Bookings'是'null'。你發現了什麼?對不起,我不清楚。 – sloth 2014-09-04 08:55:19

+0

預訂作爲虛擬資產鏈接到roomBookingsRepository,並在正常運行時拉入與派對室ID相關聯的預訂。這是EF中的一對多關係。我想我可能需要嘲笑我的DBSet來測試它。 – devfunkd 2014-09-04 19:26:30

回答

0

當您使用實體框架時,它會在從數據庫中檢索到的信息的內存中創建一個對象圖。其中一部分是它將使用虛擬屬性爲您從其他表中獲取信息。

當你編寫單元測試時,你不想訪問數據庫,所以你通常通過創建模型庫來模擬出你在這裏做的數據訪問。你遇到的問題是,因爲你沒有碰到實體框架類,它不會爲你填充你的域對象。通過創建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,可以幫助您創建您的測試對象,這可能值得您考慮。