2009-10-13 71 views
2

假設我有一個Customers表和一個帶有一對多關聯的訂單表(一個客戶可以有多個訂單)。如果我有一些我希望通過延遲加載(例如,調用customer.Orders)訪問特定客戶訂單的代碼,我該如何模擬/存根調用以便它不會觸及數據庫?單元測試Linq 2 Sql懶加載屬性

編輯:

爲了更加清楚,讓我們使用一個更具體的例子。假設我想要返回特定客戶的所有訂單。我可以把它寫像這樣使用自動生成的延遲加載特性LINQ的2 SQL提供:

Customer customer = customerRepository.GetCustomerById(customerId); 

return customer.Orders; 

然而,單元測試,這是一個有點困難。我可以剔除對GetCustomerById的調用,但我不能(據我所知)嘲笑對Orders的調用。我認爲單元測試的唯一方法是a)連接到數據庫(這會降低我的測試速度並使其變得脆弱),或者b)不使用延遲加載屬性。

不使用延遲加載的特性,我可能會重寫上面,因爲這:

return orderRepository.GetOrdersByCustomerId(customerId); 

這絕對有效,但感覺彆扭簡單地完全忽略延遲加載屬性的單元測試。

回答

2

作爲您的問題的總體答案,您可以在您將其他任何東西剔除時將該呼叫存根。

我將假設您要單元測試的代碼是數據訪問組件的使用者,因爲這是最常見的情況。如果您的程序針對接口,則只能將數據存取存根。這意味着你必須在接口後面隱藏L2S的實現細節,以便消費代碼不知道它當前使用哪個實現。

對此的一個佐證是,延遲加載是一種實現細節,您在單元測試時不必擔心,因爲單元測試根本不應該使用L2S。

當存留數據訪問層時,customers.Orders的調用通常是對存根的內存中屬性的調用。

+0

換句話說,不要使用自動生成的延遲加載屬性?而不是調用customer.Orders(其中客戶類型爲Customer,由Linq 2 Sql創建),您會創建一個OrderRepository來實現IOrderRepository並將它存根出來?這就是我一直在做的事情,但是完全忽略使用Linq 2 Sql的惰性加載功能似乎是一種浪費...... – 2009-10-13 22:54:53

+0

是的,這就是我的意思,但僅僅是因爲您針對的是一種無意識的界面實現細節並不意味着你不能使用這些功能。如果你發現L2S的延遲加載特性是有價值的,那麼儘量使用它們,但是你必須以消費者對這些細節無知的方式來做到這一點。目前微軟的ORM技術(L2S和EF)並不適合這種使用數據訪問的方式,但FWIW下一版本的EF應該得到真正的持久性無知...... – 2009-10-13 23:36:56

+0

有道理。我認爲情況可能是這樣,但希望這不是,我只是錯過了一些東西。爲了單元測試,我想我現在只會忽略延遲加載功能。 – 2009-10-14 00:31:32