簡體   English   中英

模擬復雜對象-使用Moq進行測試

[英]Mocking complex object - testing with Moq

我有以下對象結構:

public class A
{
    //...
    public B b;
    //...
}

public class B
{
    //...
    public C c;
    //...
}

public class C
{
    //...
    //...
}

我想創建一些測試來編寫數據庫訪問代碼。 為此,在每次測試之前,我都會向數據庫添加一些必要的數據(我使用的是流暢的nHibernate)。

因此,為了測試對實體A執行某些操作的某些數據庫方法,我需要將類A的對象保存到數據庫中

//...
var a = new A();
session.Save(a);
//...

這會導致nullreference異常,因為類B和C的對象也是不能為null的數據庫實體。

我的問題是如何使用Moq以優雅的方式避免此類異常。 在我真正的問題中,對象樹比這個簡化的問題要復雜得多。

您有2個選擇:

  1. 您違反了真正的Db =集成測試,這將確保您的FK約束,級聯刪除等工作正常。 我建議創建一些DemoDataDbInit類,該類將對初始演示數據進行真正的Db插入。 對於測試,您將在第一次測試之前調用一次,保存“干凈”初始化的Db的快照(克隆),然后對於后續測試,只需附加此快照 (假設您使用MSSql),這樣您的測試就可以獨立進行了。彼此(每個測試都有干凈的Db)。 您可以在CI流程中重用相同的DemoDataDbInit類,以在重新部署App后獲得一些初始虛擬數據。 測試只是假設那些數據在Db中。 Docker也在這里考慮。 遺憾的是,我忘記了一種工具的名稱-它是一種非常快的內存中Db,可作為nuget軟件包使用,它與EF&nHib兼容,可用於測試-它會提供一定的提速(我相信這不是SQLite在內存模式下)。

  2. 你反對一個模擬。 我建議您創建一些InMemoryDb類,這將是一個工廠,在內部使用Moq(或其他模擬方法)為您創建一個設置的ISession

    • session.Save(entity)會將session.Save(entity)添加到后台列表(模擬的IRepository )中
    • 它將具有一些預設組以及一些經常有用的標准數據

    vas session = new InMemoryDb.TwoCustomersWithThreeOrdersEach();

    • 它將所有實體公開為具有合適名稱(例如Customer1Order1實例屬性,以便您可以輕松訪問它們以進行其他安排或聲明。
    • 如果您願意,可以使用一個生成器,允許您編寫new InMemoryDb.TwoCustomersWithThreeOrdersEach().WithCommentOnEachOrder("my comment")等。

您將在所有測試中重用此InMemoryDb 作為InMemoryDb實現的一部分,您需要手動設置那些雙向外鍵關系/導航屬性-這樣您的查詢就不會崩潰。

在我當前的項目中,我們分別使用兩種方法進行集成和單元測試,均取得了成功。

不確定這是否是您的期望,但恐怕沒有簡單的方法可以“模擬” nHibernate施加的“約束”。 要么與真實的DB進行全力以赴,要么在模擬中進入內存-假裝FK關系是正確的。 僅供參考:EF Core具有本機內存模式

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM