簡體   English   中英

EF Moq單元測試,不確定驗證

[英]EF Moq Unit Test, unsure verify

我對單元測試完全不熟悉。 我從不同的人那里讀了許多“教程”,我決定使用msdn解決方案。

我使用這個https://msdn.microsoft.com/en-us/library/dn314429(v=vs.113).aspx作為我的測試,我感興趣的是“ 測試非查詢場景 ”。

根據這篇文章,我試着測試我簡單的CRUD的Create()動作。

這是我的代碼( FinancialAssistantEntities是我的DbContext (EF數據庫優先)):

語境:

public partial class FinancialAssistantEntities : DbContext
{
    public FinancialAssistantEntities()
        : base("name=FinancialAssistantEntities")
    {
    }
    .
    .
    .
    public virtual DbSet<FAWallet> FAWallet { get; set; }
}

存儲庫方法:(我注釋掉了我的事務的使用 ,因為從測試方法運行它會導致錯誤“在應用程序配置文件中找不到名為'FinancialAssistantEntities'的連接字符串。”),

public async Task<bool> CreateWallet(FAWallet model)
{
    using (var context = Context)
    {
        // transaction with IsolationLevel
        //using (var tran = context.Database.BeginTransaction(IsolationLevel.ReadUncommitted))
        {
            try
            {                       
                context.FAWallet.Add(model);
                //context.SaveChanges();
                await context.SaveChangesAsync();
                //tran.Commit();
                return true;
            }
            catch (Exception ex)
            {
                //tran.Rollback();
                throw ex;
            }
        }
    }
}

測試方法:

[TestMethod]
public void CreateWalletTest()
{
    var wallet = new FAWallet()
    {
        WalletId = Guid.NewGuid(),
        //WalletName = StringHelper.GenerateRandomString(12),
        // admin ID
        WalletUserId = "e6888245-1d9b-431c-a068-aa62932e47ec",
        WalletCreateDate = DateTime.Now,
        WalletEnabled = true
    };

    var mockSet = new Mock<DbSet<FAWallet>>();

    var mockContext = new Mock<FinancialAssistantEntities>();
    mockContext.Setup(x => x.FAWallet).Returns(mockSet.Object);

    var walletRepository = new FAWalletRepository(mockContext.Object);
    walletRepository.CreateWallet(wallet).Wait();

    mockSet.Verify(x => x.Add(It.IsAny<FAWallet>()), Times.Once());
    mockContext.Verify(x => x.SaveChangesAsync(), Times.Once()); 
}

首先,我不知道評論交易的使用是否是個好主意,盡管我對測試還不太了解。

其次,我的測試總是過去。 我甚至注釋掉了WalletName屬性的集合,因為這個字段不可為空,所以看起來我做錯了。

前言

在我們開始檢查您的問題的各個部分之前,讓我明確一下,主要問題不在於單元測試。 相反,它是關於面向對象編程和一些分析。

分析問題空間

讓我們看看你在評論中寫的內容:

我在其他線程下讀過像你這樣的類似答案,但我的意思是測試我的錯誤。 我有一些用戶僅部分填充的對象,之后系統自動填充其他字段,例如。 創建日期,創建用戶等。當我想念填充其中一些字段時, SaveChanges()會給我一個錯誤。

您正在從錯誤的角度接近此任務。

我為什么這么說? 因為:

  1. 您正在使用Entity Framework ORM( EF持久性模型作為行為的來源,該模型負責給定的業務交互

  2. 您希望EF進行此類驗證

  3. 您想通過EF機制測試所有這些。 你正在測試錯誤的東西

解決問題

你真正想要做的就是將你的模型融入EF的核心。 哪個不好因為:

  • 您將代碼緊密地耦合到EF,具有不必要的依賴性
  • 它使您的業務邏輯測試變得困難和緩慢
  • 業務邏輯是代碼中最重要和最有價值的部分之一,您(在理想條件下)最終會獲得報酬

現在讓我們重點關注上面的前三點。

第一:我強烈建議你創建一個可能更少依賴的對象。 為了示例,我們將其稱為實體 ,它將包含封裝的所有必需行為 就像你提到的那樣; 有公共方法來設置屬性和其他不變量。

第二:您還可以擁有保護此類型及其所有不變量所需的所有驗證。 這種驗證的常見位置可以是構造函數或接受和驗證它接收的參數的任何公共方法。 如果出現錯誤,您可以在測試中拋出自定義業務異常並對其進行斷言。

這些全部組合成一個對象,被稱為; 凝聚力

第三:既然你有一個更清潔的對象,它模擬給定的業務交互,你現在只需要完全隔離地測試這個代碼。 這是一件好事,因為它很快,它集中並且不會加載大量的依賴項(與使用EF的集成測試相比)。


一切都很順利

當然,就像所有東西一樣,這一切都需要付出代價。 那就是當你將某些東西與系統分開時,你可能會引入另一層間接。 這就是您現在需要將“域模型”映射到EF持久性模型,反之亦然。

暫無
暫無

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

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