如何跟踪實體框架核心事件以進行集成測試?

.net-core c# entity-framework-core

我們需要確保基於EF Core的代碼在測試中執行了特定類型的數據庫級操作(例如, 任何命令執行或任何事務提交)。

假設應該觸發一個真正的數據庫,我們不能通過DbContext來隔離它。怎麼看起來:

[Fact]
public async Task Test()
{
    using (var context = new FooContext())
    {
        //context-related code to produce queries and commands
    }

    Assert.True(/* any context-related transaction has been committed */);
}

可能嗎?

一般承認的答案

EF Core不提供自己的跟踪機制。但是,它記錄了許多數據庫交互事件。我們可以收集這些日誌消息並檢查它們的EventId以確定是否發生了特定操作。以下是EF Core使用的關係事件列表:

EF Core 1.1.2: RelationalEventId枚舉。

EF Core 2.0.0預覽1: RelationalEventId類(重大改變!)。

我們需要做的就是創建一個假記錄器並將其傳遞給上下文:

[Fact]
public async Task TransactionCommit_Logger_ContainsEvent()
{
    var logger = new FakeLogger();

    var factoryMock = new Mock<ILoggerFactory>();
    factoryMock.Setup(f => f.CreateLogger(It.IsAny<string>()))
        .Returns(logger);

    using (var context = new FooContext(factoryMock.Object))
    {
        using (var transaction = await context.Database.BeginTransactionAsync())
        {
            transaction.Commit();
        }
    }

    Assert.True(logger.Events.Contains((int)RelationalEventId.CommittingTransaction));
}

FakeLogger將記錄的事件ID添加到“ Events列表中。

public class FakeLogger : ILogger
{
    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
        Func<TState, Exception, string> formatter)
    {
        Events.Add(eventId.Id);
    }

    public List<int> Events { get; set; } = new List<int>();

    public bool IsEnabled(LogLevel logLevel) => true;

    public IDisposable BeginScope<TState>(TState state) => null;
}    

調用UseLoggerFactory將工廠實例附加到上下文:

public class FooContext : FooParentContext
{
    private readonly ILoggerFactory _loggerFactory;

    public FooContext() { }

    public FooContext(ILoggerFactory loggerFactory)
    {
        _loggerFactory = loggerFactory;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);

        optionsBuilder.UseLoggerFactory(_loggerFactory);
    }
}

PS你可以更深入地分析日誌消息甚至EF生成的原始SQL



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow