使用TestServer做集成测试时Visual Studio测试运行器无控制台日志如何解决
根因说明
- Startup中自定义的
ILoggerFactory被using块包裹,ConfigureServices执行完成后就会被销毁,后续接口请求过程中生成的日志无法正常写入控制台输出目标。 TestServer运行Web应用时的宿主输出上下文和测试运行器的捕获上下文相互独立,默认不会将Web应用的控制台输出转发到测试运行器的捕获范围,只有Debug级别的输出会统一写入系统的Debug窗口被捕获。
解决步骤
1. 实现NUnit日志输出提供器
自定义日志提供器将Web应用的日志直接输出到NUnit的测试上下文,该上下文的输出会被VS测试运行器自动捕获:
public class NUnitLoggerProvider : ILoggerProvider { public ILogger CreateLogger(string categoryName) => new NUnitLogger(categoryName); public void Dispose() {} } public class NUnitLogger : ILogger { private readonly string _categoryName; public NUnitLogger(string categoryName) => _categoryName = categoryName; public IDisposable BeginScope<TState>(TState state) => null; public bool IsEnabled(LogLevel logLevel) => logLevel != LogLevel.None; public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) { if (!IsEnabled(logLevel)) return; var message = formatter(state, exception); if (exception != null) message += Environment.NewLine + exception; TestContext.Out.WriteLine($"[{logLevel}] {_categoryName}: {message}"); } }
你也可以直接安装NuGet包NUnit.Extensions.Logging,直接使用内置的AddNUnit()扩展方法,无需自定义实现。
2. 调整TestServer的日志配置
在构造TestServer时统一配置日志规则,将NUnit日志提供器注入到Web宿主的日志体系中:
public class Tests { private TestServer _testServer; private HttpClient _httpClient; [OneTimeSetUp] public void SetupTestServerAndHttpClient() { _testServer = new TestServer(new WebHostBuilder() .ConfigureLogging((ctx, logBuilder) => { logBuilder.ClearProviders(); logBuilder.AddDebug(); logBuilder.AddConsole(); // 注入自定义的NUnit日志提供器 logBuilder.AddProvider(new NUnitLoggerProvider()); // 若使用NuGet包则替换为 logBuilder.AddNUnit(); logBuilder.SetMinimumLevel(LogLevel.Information); }) .UseStartup<MyWebAPIProject.Startup>()); _httpClient = _testServer.CreateClient(); } [OneTimeTearDown] public void CleanUp() { _httpClient.Dispose(); _testServer.Dispose(); } [Test] public async Task TestMyAPIMethod() { await _httpClient.PostAsync("myapiroute", "method param"); } }
3. 修正Startup中的LoggerFactory使用逻辑
删除Startup中自定义创建ILoggerFactory的代码,直接从DI容器获取已经配置好的日志工厂,避免提前销毁问题:
public void ConfigureServices(IServiceCollection services) { // 从DI容器获取统一配置的日志工厂 var serviceProvider = services.BuildServiceProvider(); var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>(); var loggerForModule = loggerFactory.CreateLogger("Module.Logging"); ModuleInitializer.Initialize(loggerForModule); // 其余原有服务配置保持不变 }
验证
修改完成后运行测试,打开VS测试运行器的「测试详细信息」面板,即可看到所有模块输出的日志内容。
内容的提问来源于stack exchange,提问作者Neil W
相关产品推荐
相关产品推荐

