如何跟踪Entity Framework Core事件以进行集成测试?

4
我们需要确保在测试中,基于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 */);
}

这可能吗?


假设您的事务是“cud”,您只需读取数据并验证其正确性即可。 - Arijoon
1个回答

5

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);
    }
}

P.S. 你甚至可以更深入地分析日志消息,甚至是EF生成的原始SQL


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接