2

EF Core 測試小技巧 - 快速建立資料表

 2 years ago
source link: https://blog.darkthread.net/blog/ef-core-ensurecreated/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

EF Core 測試小技巧 - 快速建立資料表

2022-04-11 09:41 AM 1 523

截至目前,我的 EF Core 範例都是用 dotnet ef migrations create 產生建立(或升級) Schema 所需程式,再透過 dotnet ef database update 或 DbContext.Database.Migrate() 套用 Migration 建立或修改資料表。

但在雛型驗證階段或跑自動測試,有個更省事的做法 - DbContext.Database.EnsureCreated(),其執行規則為:

  1. 若資料庫存在且有任何資料表,不執行動作,傳回 false
  2. 若資料庫存在且沒有任何資料表,則使用 EF Model 建立資料表
  3. 若資料庫不存在,則先建立資料庫再依 EF Model 建立資料表

EnsureCreated() 的缺點是適用空白資料庫全新建立,不像 Migration 可依資料庫現況增減資料表、欄位、索引,再套用現存資料庫將 Schema 更新到最新狀態。用 EnsureCreated() 建立的資料表,之後也無法再用 Migration 套用更新。

實驗驗證或自動測試時,資料庫通常測完即抛,沒有後續更新問題,便適合使用 EnsureCreated(),省去建立 Migration 程序。

以昨天的 StaticFileDbContext 為實例,我想對它做自動測試,試試資料表寫入是否正常,可以這樣做:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.Data.Sqlite;
using Drk.AspNetCore.FileProviders;
using System.Linq;
using System.Text;
namespace test_dbctx;

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        var dbPath = "test.sqlite";
		// 清除之前殘留資料庫檔案
        if (File.Exists(dbPath)) File.Delete(dbPath);
        var opt = new DbContextOptionsBuilder<StaticFileDbContext>()
            .UseSqlite($"data source={dbPath}").Options;
        var ctx= new StaticFileDbContext(opt);
		// 建立資料表
        ctx.Database.EnsureCreated();
        var resp = new StaticFileDbRepository(ctx);
        Assert.AreEqual(ctx.StaticFileIndices.Count(), 0);
        var userId = "jeffrey";
        var clientIp = "::1";
        resp.UpdateFile("/test.txt", Encoding.UTF8.GetBytes("ABC"), userId, clientIp);
        Assert.AreEqual(ctx.StaticFileIndices.Count(), 2);
        var testTxt = Encoding.UTF8.GetString(resp.ReadFile("/test.txt").Content);
        Assert.AreEqual(testTxt, "ABC");
    }
}

使用 .NET CLI 一鏡到底之測試程序如下:

dotnet new mstest -o test-dbctx
cd test-dbctx
dotnet add package Drk.AspNetCore.FileProviders
rem 將 UnitTest1.cs 換成上面的程式碼
dotnet test

測試成功!

不過,由於 EnsureCreated() 的偵測條件是資料庫不存在任何資料表,若有多個 DbContext 共用資料庫,只有第一個執行 EnsureCreated() 的 DbContext 會建立資料表,第二個 DbContext EnsureCreated() 時會因已存在第一個 DbContext 的資料表而不執行動作(如下圖),此時需依賴 Migration 才能完整建立。單元測試多半聚焦單一 DbContext,倒是可安心使用。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK