Fuff數據庫時,Effort- FirstOrDefault返回null

c# effort entity-framework mocking unit-testing

我正在嘗試為我的項目創建一些單元測試,經過多次挖掘後我發現了Effort,這個想法很棒,它嘲笑數據庫而不是偽造DBContext,順便說一句,這很難讓它正確使用複雜的架構。

但是我試圖在我將其專門添加到由Effort創建的內存數據庫後獲取用戶的電子郵件,這裡是代碼

MyContext contextx = new MyContext(Effort.DbConnectionFactory.CreateTransient());

var client = new Client
{
    ClientId = 2,
    PersonId = 3,
    Person = new Person
    {
        PersonId = 3,
        EMail = "xxxxx@gmail.com"
    }
};
contextx.Client.Add(client); //<-- client got added, I checked it and is there

var email = contextx.Client.Select(c => c.Person.EMail).FirstOrDefault(); 

在上面的最後一行我不能讓它返回電子郵件xxxx@gmail.com而是總是返回null。

有任何想法嗎?

一般承認的答案

回答你的直接問題

對於您提出的具體問題,我建議兩件事:

  1. 看看contextx.Client.ToArray() ,看看你在該集合中真正擁有多少成員。可能是Client集合實際上是空的,在這種情況下,您確實會為null。或者,可能是Client集合中的第一個元素對於EMail具有空值。

  2. 如果在查詢DbContext上的Client集合之前調用了contextx.SaveChanges() ,行為會如何變化?我很想知道調用SaveChanges是否會導致新插入的值存在於集合中。這確實不應該是必需的,但是Effort和DbContext之間可能存在一些奇怪的交互。

編輯: SaveChanges()原來是答案。

一般測試建議

由於您使用“單元測試”標籤標記了這個問題,我將根據我作為單元測試從業者和教練花費的十年時間提供一些一般的單元測試建議。 單元測試是關於單獨測試應用程序的各個小部分。通常,這意味著單元測試只能同時與幾個類進行交互。這也意味著單元測試不應該依賴於外部庫或依賴項(例如數據庫)。相反, 集成測試會立即執行系統的更多部分,並且可能對數據庫之類的內容具有外部依賴性。

雖然這看起來似乎是對術語的狡辯,但這些術語對於將測試的實際意圖傳達給團隊中的其他成員非常重要。

在這種情況下,要么您真的想要對依賴於DbContext的某些功能進行單元測試,要么您正在嘗試測試您的數據訪問層。如果您正在嘗試編寫一個直接依賴於DbContext的獨立單元測試,那麼您需要打破對DbContext的依賴。我將在下面的破壞DbContext的依賴關係中解釋這一點。否則,您真的嘗試集成測試您的DbContext,包括您的實體如何映射。在這種情況下,我總是發現最好隔離這些測試並使用真實(本地)數據庫。您可能希望使用與您在生產中使用的相同種類的本地安裝的數據庫。通常,SqlExpress工作得很好。將測試指向測試可以完全丟棄的數據庫實例。在運行每個測試之前,讓測試刪除所有現有數據。然後,他們可以設置他們需要的任何數據,而無需擔心現有數據會發生衝突。

打破DbContext的依賴

那麼,當業務邏輯依賴於訪問DbContext時,如何編寫好的單元測試? 你沒有。

在我使用Entity Framework進行數據持久化的應用程序中,我確保對DbContext訪問包含在一個單獨的數據訪問項目中。通常,我將創建實現Repository模式的類,並允許這些類依賴於DbContext 。因此,在這種情況下,我將創建一個實現IClientRepository接口的ClientRepository 。界面看起來像這樣:

public interface IClientRepository {

    Client GetClientByEMail(string email);

}

然後,任何需要訪問該方法的類都可以使用基本的stub / mock / whatever進行單元測試。沒有什麼可以擔心嘲笑DbContext 。您的數據訪問層已包含,您可以使用真實數據庫對其進行全面測試。有關如何測試數據訪問層的一些建議,請參見上文。

作為額外的好處,此接口的實現定義了在單個統一的位置通過電子郵件地址查找Client的含義。 IClientRepository接口允許您快速回答“我們如何查詢系統中的Client實體?”這一問題。

DbContext的依賴與測試問題的大小基本相同,因為允許域類依賴於連接字符串並且在任何地方都有ADO.Net代碼。這意味著您必須創建一個包含真實數據的真實數據存儲(即使使用虛假數據庫)。但是,如果您在特定數據訪問程序DbContext包含對DbContext訪問權限,則會發現單元測試更容易編寫。

就項目組織而言,我通常只允許我的數據訪問項目參考實體框架。我將有一個單獨的Core項目,我在其中定義實體。我還將在Core項目中定義數據訪問接口。然後,具體的接口實現被放入數據訪問項目中。您的解決方案中的大多數項目可以簡單地依賴於Core項目,只有頂級可執行文件或Web項目才真正需要依賴於數據訪問項目。




許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因