如何跟踪 Entity Framework Core 事件以进行集成测试? [英] How to trace an Entity Framework Core event for integration testing?

查看:27
本文介绍了如何跟踪 Entity Framework Core 事件以进行集成测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们需要确保基于 EF Core 的代码已执行特定类型的数据库级操作(例如,any 命令执行或 any 事务提交).

We need to ensure that EF Core-based code has performed a specific kind of database-level operation under test (for example, any command execution or any transaction commit).

假设应该触发一个真实的数据库,并且我们不能通过 DbContext 模拟来隔离它.怎么看:

Let's suppose a real database should be triggered and we can't isolate it by DbContext mocking. How could it look:

[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 doesn't provide its own tracing mechanism. However, it logs a lot of database interaction events. We could gather these log messages and check their EventId to determine did a specific operation occur or not. Here is the list of relational events used by EF Core:

EF 核心 1.1.2:RelationalEventId 枚举.

EF Core 1.1.2: RelationalEventId enum.

EF Core 2.0.0 预览版 1:RelationalEventId 类(重大更改!).

EF Core 2.0.0 preview 1: RelationalEventId class (breaking change!).

我们需要做的就是创建一个伪造的记录器并将其传递给上下文:

All we need to do is create a fake logger and pass it to context:

[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 列表.

FakeLogger adds a logged event id to the Events list.

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 将工厂实例附加到上下文:

Call UseLoggerFactory to attach a factory instance to a context:

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

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

P.S. You could go even deeper and analyze log message or even raw SQL produced by EF.

这篇关于如何跟踪 Entity Framework Core 事件以进行集成测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆