[ASP.NET Core] 在單元測試中替換掉 DbContext

在寫單元測試時,難免都會遇到 DbContext 的相依,在 ASP.NET Core 裡面什麼服務都是走DI,也包含了DbContext,這讓替換 DbContext 變得更容易了

在寫單元測試時,難免都會遇到 DbContext 的相依,在 ASP.NET Core 裡面什麼服務都是走DI,也包含了DbContext,這讓替換 DbContext 變得更容易了


準備簡單的待測試邏輯,並且使用SqlServer

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.5"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.5"/>
public class MemberService
{
    private readonly ITestDbContext _dbContext;

    public MemberService(ITestDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public bool MemberIsExists(string id)
    {
        var member = _dbContext.Member.FirstOrDefault(r => r.Id == id);
        return member != null;
    }
}

public class TestDbContext : DbContext, ITestDbContext
{
    public TestDbContext(DbContextOptions<TestDbContext> options)
        : base(options)
    {
    }

    public DbSet<Member> Member { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    }
}

在測試裡就可以透過 TestDbContext 的參數 DbContextOptions<TestDbContext> 來建立測試用的DB,並注入 Service,在測試我改用 InMemoryDb(看個人需求也可以用Sqlite)

<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.5" />
public class UnitTest1
{
    private readonly TestDbContext _testDbContext;
    private readonly MemberService _memberService;

    public UnitTest1()
    {
        var dbContextOptions = new DbContextOptionsBuilder<TestDbContext>()
                                   .UseInMemoryDatabase(Guid.NewGuid().ToString("N"))
                                   .Options;
        _testDbContext = new TestDbContext(dbContextOptions);
        _memberService = new MemberService(_testDbContext);
    }

    [Fact]
    public void Is()
    {
        _testDbContext.Member.Add(new Member()
        {
            Id = "id"
        });
        _testDbContext.SaveChanges();

        var isExists = _memberService.MemberIsExists("id");
        Assert.True(isExists);
    }

    [Fact]
    public void Not()
    {
        var isExists = _memberService.MemberIsExists("id");
        Assert.False(isExists);
    }
}

接著簡單的測試就誕生了,可以依照自己的需求替換DB,或是準備當次測試需要的資料


SampleCode https://github.com/ianChen806/UnitTestDbSample