EF Core 測試小技巧 - 快速建立資料表
1 |
截至目前,我的 EF Core 範例都是用 dotnet ef migrations create 產生建立(或升級) Schema 所需程式,再透過 dotnet ef database update 或 DbContext.Database.Migrate() 套用 Migration 建立或修改資料表。
但在雛型驗證階段或跑自動測試,有個更省事的做法 - DbContext.Database.EnsureCreated(),其執行規則為:
- 若資料庫存在且有任何資料表,不執行動作,傳回 false
- 若資料庫存在且沒有任何資料表,則使用 EF Model 建立資料表
- 若資料庫不存在,則先建立資料庫再依 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,倒是可安心使用。
Introduce to EF Core EnsureCreated(), including pros and limitations.
Comments
# by Cash
E2E 測試的時候很好用 !!