diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/TestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/TestBase.cs index 5171f903455..a88a67a5840 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/TestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/TestBase.cs @@ -90,6 +90,8 @@ protected TestBase(ITestOutputHelper testOutput) // Give this thread a name, so it's easier to find in the VS Threads window. Thread.CurrentThread.Name ??= "Main Thread"; + + ThrowingTraceListener.AddToListeners(); } Task IAsyncLifetime.InitializeAsync() => InitializeAsync(); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/ThrowingTraceListener.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/ThrowingTraceListener.cs new file mode 100644 index 00000000000..2096fa6ba44 --- /dev/null +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/ThrowingTraceListener.cs @@ -0,0 +1,88 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; + +namespace Microsoft.AspNetCore.Razor.Test.Common; + +public sealed class ThrowingTraceListener : TraceListener +{ + private static bool s_throwingTraceListenerAdded; + private static readonly object s_gate = new(); + + public static void AddToListeners() + { + lock (s_gate) + { + if (s_throwingTraceListenerAdded) + { + return; + } + + var sawThrowingTraceListener = false; + var listeners = Trace.Listeners; + for (var i = listeners.Count - 1; i >= 0; i--) + { + switch (listeners[i]) + { + case DefaultTraceListener listener: + // Don't show assert UI during test runs + listener.AssertUiEnabled = false; + break; + case ThrowingTraceListener: + sawThrowingTraceListener = true; + break; + } + } + + if (!sawThrowingTraceListener) + { + // Add an instance of the ThrowingTraceListener so that Debug.Assert and Debug.Fail + // throw exceptions during test runs. + listeners.Add(new ThrowingTraceListener()); + } + + s_throwingTraceListenerAdded = true; + } + } + + public override void Fail(string? message, string? detailMessage) + { + throw new InvalidOperationException( + (string.IsNullOrEmpty(message) ? "Assertion failed" : message) + + (string.IsNullOrEmpty(detailMessage) ? "" : Environment.NewLine + detailMessage)); + } + + public override void Write(object? o) + { + } + + public override void Write(object? o, string? category) + { + } + + public override void Write(string? message) + { + } + + public override void Write(string? message, string? category) + { + } + + public override void WriteLine(object? o) + { + } + + public override void WriteLine(object? o, string? category) + { + } + + public override void WriteLine(string? message) + { + } + + public override void WriteLine(string? message, string? category) + { + } +} diff --git a/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/AbstractIntegrationTest.cs b/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/AbstractIntegrationTest.cs index c187f971ec0..420a1447450 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/AbstractIntegrationTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/AbstractIntegrationTest.cs @@ -3,6 +3,7 @@ using System; using System.Threading; +using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.VisualStudio.Extensibility.Testing; using Xunit; using Xunit.Sdk; @@ -38,6 +39,8 @@ public abstract class AbstractIntegrationTest : AbstractIdeIntegrationTest public override async Task InitializeAsync() { + ThrowingTraceListener.AddToListeners(); + await base.InitializeAsync(); } }