【问题标题】:Getting EF Core to output SQL statements to xUnit's ITestOutputHelper获取EF核心以将SQL语句输出到XUNIT的ITESTOUTPUTHELPEL
【发布时间】:2020-08-23 16:11:45
【问题描述】:

我正在使用 EF Core 2.2.4 并试图找出 EF Core 在我们的单元测试中发送到我们的 SQLite 数据库的 SQL 语句。由于我们使用的是 xUnit (2.4.1),我们必须将日志消息写入 ITestOutputHelper 实例 xUnit 正在注入我们的测试类而不是控制台。对于控制台,我找到了这段代码:

private static ILoggerFactory GetLoggerFactory()
{
    IServiceCollection serviceCollection = new ServiceCollection();
    serviceCollection.AddLogging(builder =>
        builder.AddConsole()
            .AddFilter(DbLoggerCategory.Database.Command.Name,
                LogLevel.Information));
    return serviceCollection.BuildServiceProvider()
        .GetService<ILoggerFactory>();
}

如何将此输出重定向到ITestOutputHelper.WriteLine()

【问题讨论】:

    标签: entity-framework-core xunit xunit.net ef-core-2.2


    【解决方案1】:

    首先,创建一些样板日志记录代码以允许输出到 ITestOutputHelper:

    class TestLoggerProvider : ILoggerProvider
    {
        ITestOutputHelper _output;
    
        public TestLoggerProvider(ITestOutputHelper output)
            => _output = output;
    
        public ILogger CreateLogger(string categoryName)
            => new TestLogger(categoryName, _output);
    
        public void Dispose()
        {
        }
    }
    
    class TestLogger : ILogger
    {
        string _categoryName;
        ITestOutputHelper _output;
    
        public TestLogger(string categoryName, ITestOutputHelper output)
        {
            _categoryName = categoryName;
            _output = output;
        }
    
        public bool IsEnabled(LogLevel logLevel)
            // NB: Only logging things related to commands, but you can easily expand
            //     this
            => _categoryName == DbLoggerCategory.Database.Command.Name;
    
        public void Log<TState>(
            LogLevel logLevel,
            EventId eventId,
            TState state,
            Exception exception,
            Func<TState, Exception, string> formatter)
        {
            // TODO: Customize the formatting even more if you want
            //if (eventId == RelationalEventId.CommandExecuting)
            //{
            //    var structure = (IReadOnlyList<KeyValuePair<string, object>>)state;
            //    var parameters = (string)structure.First(i => i.Key == "parameters")
            //        .Value;
            //    var commandText = (string)structure.First(i => i.Key == "commandText")
            //        .Value;
            //}
    
            _output.WriteLine(formatter(state, exception));
        }
    
        public IDisposable BeginScope<TState>(TState state)
            => null;
    }
    

    接下来,确保您的 DbContext 可以接受外部选项。

    class MyDbContext : DbContext
    {
        public MyDbContext(DbContextOptions<MyDbContext> options)
            : base(options)
        {
        }
    }
    

    最后,把它全部连接起来。这是为每个测试创建新上下文的示例。使用classcollection fixture 来延长上下文的生命周期。

    public class UnitTest1 : IDisposable
    {
        IServiceProvider _serviceProvider;
        MyDbContext _db;
    
        public UnitTest1(ITestOutputHelper output)
        {
            _serviceProvider = new ServiceCollection()
                .AddLogging(x => x.AddProvider(new TestLoggerProvider(output)))
                .AddEntityFrameworkSqlite()
                .BuildServiceProvider();
    
            _db = new MyDbContext(
                new DbContextOptionsBuilder<MyDbContext>()
                    // Don't call UseLoggerFactory! (a new service provider would be
                    // created every time without ever getting disposed)
                    .UseInternalServiceProvider(_serviceProvider)
                    .UseSqlite("Data Source=:memory:")
                    .Options);
        }
    
        [Fact]
        public void Test1()
        {
            _db.Database.ExecuteSqlRaw("-- Can you see me?");
        }
    
        public void Dispose()
        {
            _db.Dispose();
            (_serviceProvider as IDisposable)?.Dispose();
        }
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-09
    • 2020-07-29
    • 1970-01-01
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多