diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index d19c3a99..feafd8ad 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -21,9 +21,15 @@ env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 pg_db: marten_testing pg_user: postgres + # CONFIGURATION binds to the Nuke [Parameter] of the same name (Nuke reads parameters from the + # environment), so it genuinely selects the Release build. FRAMEWORK and + # DISABLE_TEST_PARALLELIZATION used to sit here too but bound to nothing: there is no Framework + # parameter, and no test project, runner config, or build target ever read the latter. The two + # suites that actually must not run concurrently (CodegenTests mutates process-wide statics and + # compiles assemblies; CommandLineTests redirects Console) declare that in code via + # [assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)], which xunit v3 still + # honors, so the serialization is enforced where it can't be silently dropped. CONFIGURATION: Release - FRAMEWORK: net9.0 - DISABLE_TEST_PARALLELIZATION: true NUKE_TELEMETRY_OPTOUT: true jobs: diff --git a/Directory.Packages.props b/Directory.Packages.props index d341748b..8132fade 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -80,11 +80,11 @@ - + - - + + diff --git a/src/CodegenTests.FSharp/CodegenTests.FSharp.csproj b/src/CodegenTests.FSharp/CodegenTests.FSharp.csproj index 757bbe0a..a806e676 100644 --- a/src/CodegenTests.FSharp/CodegenTests.FSharp.csproj +++ b/src/CodegenTests.FSharp/CodegenTests.FSharp.csproj @@ -24,7 +24,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/CodegenTests.FSharp/FSharpCompilationGate.cs b/src/CodegenTests.FSharp/FSharpCompilationGate.cs index 35af2488..82ae7c40 100644 --- a/src/CodegenTests.FSharp/FSharpCompilationGate.cs +++ b/src/CodegenTests.FSharp/FSharpCompilationGate.cs @@ -1,6 +1,5 @@ using System.Diagnostics; using Shouldly; -using Xunit.Abstractions; namespace CodegenTests.FSharp; diff --git a/src/CodegenTests/CodeGeneration_ordering_determinism.cs b/src/CodegenTests/CodeGeneration_ordering_determinism.cs index fc7cbacd..75b444d5 100644 --- a/src/CodegenTests/CodeGeneration_ordering_determinism.cs +++ b/src/CodegenTests/CodeGeneration_ordering_determinism.cs @@ -3,7 +3,6 @@ using JasperFx.CodeGeneration.Model; using Shouldly; using Xunit; -using Xunit.Abstractions; namespace CodegenTests; diff --git a/src/CodegenTests/CodegenTests.csproj b/src/CodegenTests/CodegenTests.csproj index 0768ed8b..697b779e 100644 --- a/src/CodegenTests/CodegenTests.csproj +++ b/src/CodegenTests/CodegenTests.csproj @@ -10,7 +10,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/CodegenTests/FSharpControlFlowTests.cs b/src/CodegenTests/FSharpControlFlowTests.cs index 5088aac6..28049f5b 100644 --- a/src/CodegenTests/FSharpControlFlowTests.cs +++ b/src/CodegenTests/FSharpControlFlowTests.cs @@ -2,7 +2,6 @@ using JasperFx.CodeGeneration.Frames; using JasperFx.CodeGeneration.Model; using Shouldly; -using Xunit.Abstractions; namespace CodegenTests; diff --git a/src/CodegenTests/GeneratedTypeTests.cs b/src/CodegenTests/GeneratedTypeTests.cs index 9f21b4db..c3c1ac5c 100644 --- a/src/CodegenTests/GeneratedTypeTests.cs +++ b/src/CodegenTests/GeneratedTypeTests.cs @@ -2,7 +2,6 @@ using JasperFx.CodeGeneration.Model; using JasperFx.Core; using Shouldly; -using Xunit.Abstractions; namespace CodegenTests; diff --git a/src/CodegenTests/MethodCallTester.cs b/src/CodegenTests/MethodCallTester.cs index e9054ec0..9d84063a 100644 --- a/src/CodegenTests/MethodCallTester.cs +++ b/src/CodegenTests/MethodCallTester.cs @@ -3,7 +3,6 @@ using JasperFx.CodeGeneration.Model; using NSubstitute; using Shouldly; -using Xunit.Sdk; namespace CodegenTests; @@ -478,5 +477,15 @@ public Task GetString() public interface IMartenOp { - + +} + +/// +/// A return type for the MethodCallTarget probes below. The tests only assert that +/// MethodCall infers this exact type (and the argument name derived from it), so any reference +/// type does; it previously borrowed Xunit.Sdk.ErrorMessage via a stray `using Xunit.Sdk`, +/// which quietly tied a codegen test to xunit's internals and broke on the v3 upgrade. +/// +public class ErrorMessage +{ } \ No newline at end of file diff --git a/src/CodegenTests/Samples/Frames.cs b/src/CodegenTests/Samples/Frames.cs index dec0f56d..d086ab49 100644 --- a/src/CodegenTests/Samples/Frames.cs +++ b/src/CodegenTests/Samples/Frames.cs @@ -3,7 +3,6 @@ using JasperFx.CodeGeneration.Frames; using JasperFx.CodeGeneration.Model; using Xunit; -using Xunit.Abstractions; namespace CodegenTests.Samples; diff --git a/src/CodegenTests/Samples/HelloWorld.cs b/src/CodegenTests/Samples/HelloWorld.cs index 06cd78f5..3b4ab63d 100644 --- a/src/CodegenTests/Samples/HelloWorld.cs +++ b/src/CodegenTests/Samples/HelloWorld.cs @@ -2,7 +2,6 @@ using System.Linq; using JasperFx.RuntimeCompiler; using Xunit; -using Xunit.Abstractions; namespace CodegenTests.Samples; diff --git a/src/CodegenTests/Samples/InjectedFieldUsage.cs b/src/CodegenTests/Samples/InjectedFieldUsage.cs index 069437a2..a96305f6 100644 --- a/src/CodegenTests/Samples/InjectedFieldUsage.cs +++ b/src/CodegenTests/Samples/InjectedFieldUsage.cs @@ -3,7 +3,6 @@ using JasperFx.CodeGeneration.Frames; using JasperFx.CodeGeneration.Model; using Xunit; -using Xunit.Abstractions; namespace CodegenTests.Samples; diff --git a/src/CodegenTests/Samples/UsingSourceWriter.cs b/src/CodegenTests/Samples/UsingSourceWriter.cs index 78567679..54fdb234 100644 --- a/src/CodegenTests/Samples/UsingSourceWriter.cs +++ b/src/CodegenTests/Samples/UsingSourceWriter.cs @@ -1,7 +1,6 @@ using System; using JasperFx.CodeGeneration; using Xunit; -using Xunit.Abstractions; namespace CodegenTests.Samples; diff --git a/src/CodegenTests/Services/BruteForceTests.cs b/src/CodegenTests/Services/BruteForceTests.cs index 0823fed9..7b393cd5 100644 --- a/src/CodegenTests/Services/BruteForceTests.cs +++ b/src/CodegenTests/Services/BruteForceTests.cs @@ -5,7 +5,6 @@ using JasperFx.RuntimeCompiler; using Microsoft.Extensions.DependencyInjection; using Shouldly; -using Xunit.Abstractions; namespace CodegenTests.Services; diff --git a/src/CodegenTests/Services/inline_enumerable_with_mixed_lifetimes.cs b/src/CodegenTests/Services/inline_enumerable_with_mixed_lifetimes.cs index 5e179293..f590daee 100644 --- a/src/CodegenTests/Services/inline_enumerable_with_mixed_lifetimes.cs +++ b/src/CodegenTests/Services/inline_enumerable_with_mixed_lifetimes.cs @@ -7,7 +7,6 @@ using JasperFx.RuntimeCompiler; using Microsoft.Extensions.DependencyInjection; using Shouldly; -using Xunit.Abstractions; namespace CodegenTests.Services; diff --git a/src/CodegenTests/Services/keyed_constructor_injection.cs b/src/CodegenTests/Services/keyed_constructor_injection.cs index 98fe597e..45ac0729 100644 --- a/src/CodegenTests/Services/keyed_constructor_injection.cs +++ b/src/CodegenTests/Services/keyed_constructor_injection.cs @@ -6,7 +6,6 @@ using Microsoft.Extensions.DependencyInjection; using Shouldly; using Xunit; -using Xunit.Abstractions; namespace CodegenTests.Services; diff --git a/src/CodegenTests/Services/keyed_service_location.cs b/src/CodegenTests/Services/keyed_service_location.cs index af92e298..25f37cc0 100644 --- a/src/CodegenTests/Services/keyed_service_location.cs +++ b/src/CodegenTests/Services/keyed_service_location.cs @@ -5,7 +5,6 @@ using JasperFx.RuntimeCompiler; using Microsoft.Extensions.DependencyInjection; using Shouldly; -using Xunit.Abstractions; namespace CodegenTests.Services; diff --git a/src/CommandLineTests/CommandExecutorTester.cs b/src/CommandLineTests/CommandExecutorTester.cs index c520115e..4c54f5ac 100644 --- a/src/CommandLineTests/CommandExecutorTester.cs +++ b/src/CommandLineTests/CommandExecutorTester.cs @@ -2,6 +2,7 @@ using JasperFx.CommandLine; using JasperFx.Core; using Shouldly; +using Spectre.Console; namespace CommandLineTests { @@ -23,6 +24,17 @@ public CommandExecutorTester() { Console.SetOut(theOutput); + // CommandExecutor renders failures through Spectre's AnsiConsole, which caches the + // TextWriter it binds to on first use anywhere in the process. Console.SetOut alone + // therefore does NOT redirect the failure path -- whichever test touched Spectre first + // has already pinned the writer. That made run_an_async_command_that_fails pass or fail + // purely on test ordering (it survived xunit v2's order and broke under v3's). Bind + // Spectre explicitly so this class captures failure output regardless of order. + AnsiConsole.Console = AnsiConsole.Create(new AnsiConsoleSettings + { + Out = new AnsiConsoleOutput(theOutput) + }); + executor = CommandExecutor.For(_ => { _.RegisterCommands(GetType().GetTypeInfo().Assembly); diff --git a/src/CommandLineTests/CommandLineTests.csproj b/src/CommandLineTests/CommandLineTests.csproj index 87221f58..177cd71b 100644 --- a/src/CommandLineTests/CommandLineTests.csproj +++ b/src/CommandLineTests/CommandLineTests.csproj @@ -8,7 +8,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/CoreTests/Core/data_segregation.cs b/src/CoreTests/Core/data_segregation.cs index 9633fbdb..fb8efd77 100644 --- a/src/CoreTests/Core/data_segregation.cs +++ b/src/CoreTests/Core/data_segregation.cs @@ -1,5 +1,4 @@ using JasperFx.Core; -using Xunit.Abstractions; namespace CoreTests.Core; diff --git a/src/CoreTests/CoreTests.csproj b/src/CoreTests/CoreTests.csproj index c3124487..3be00c2a 100644 --- a/src/CoreTests/CoreTests.csproj +++ b/src/CoreTests/CoreTests.csproj @@ -10,7 +10,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/DocSamples/DocSamples.csproj b/src/DocSamples/DocSamples.csproj index d0539fe1..3daffb5b 100644 --- a/src/DocSamples/DocSamples.csproj +++ b/src/DocSamples/DocSamples.csproj @@ -5,16 +5,13 @@ false - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + diff --git a/src/EventStoreTests/EventStoreTests.csproj b/src/EventStoreTests/EventStoreTests.csproj index 65c7ddfb..7f50890f 100644 --- a/src/EventStoreTests/EventStoreTests.csproj +++ b/src/EventStoreTests/EventStoreTests.csproj @@ -8,7 +8,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/EventStoreTests/TestingSupport/TestLogger.cs b/src/EventStoreTests/TestingSupport/TestLogger.cs index 145431e5..8d96df15 100644 --- a/src/EventStoreTests/TestingSupport/TestLogger.cs +++ b/src/EventStoreTests/TestingSupport/TestLogger.cs @@ -1,7 +1,6 @@ using System.Diagnostics; using JasperFx.Core.Reflection; using Microsoft.Extensions.Logging; -using Xunit.Abstractions; namespace EventStoreTests.TestingSupport; diff --git a/src/EventTests/EventTests.csproj b/src/EventTests/EventTests.csproj index 803e7cb2..7a806155 100644 --- a/src/EventTests/EventTests.csproj +++ b/src/EventTests/EventTests.csproj @@ -11,7 +11,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/EventTests/Projections/SliceGroupTests.cs b/src/EventTests/Projections/SliceGroupTests.cs index 77775aa8..27554d71 100644 --- a/src/EventTests/Projections/SliceGroupTests.cs +++ b/src/EventTests/Projections/SliceGroupTests.cs @@ -544,9 +544,12 @@ Task IProjectionStorage.LoadAsync(string id, CancellationTok throw new NotImplementedException(); } + // Part of the IProjectionStorage contract this class self-stubs, NOT xunit lifecycle -- but + // xunit v3 disposes a test class that implements IAsyncDisposable, so a throwing stub here + // fails every test in the class during teardown. Nothing in these tests needs disposal. ValueTask IAsyncDisposable.DisposeAsync() { - throw new NotImplementedException(); + return ValueTask.CompletedTask; } Task> IStorageOperations.FetchProjectionStorageAsync(string tenantId, CancellationToken cancellationToken) diff --git a/src/EventTests/TestingSupport/TestLogger.cs b/src/EventTests/TestingSupport/TestLogger.cs index 38f2bd49..80ed6ed5 100644 --- a/src/EventTests/TestingSupport/TestLogger.cs +++ b/src/EventTests/TestingSupport/TestLogger.cs @@ -1,7 +1,6 @@ using System.Diagnostics; using JasperFx.Core.Reflection; using Microsoft.Extensions.Logging; -using Xunit.Abstractions; namespace EventTests.TestingSupport; diff --git a/src/JasperFx.Aspire.Tests/JasperFx.Aspire.Tests.csproj b/src/JasperFx.Aspire.Tests/JasperFx.Aspire.Tests.csproj index 935b095a..58fd08d2 100644 --- a/src/JasperFx.Aspire.Tests/JasperFx.Aspire.Tests.csproj +++ b/src/JasperFx.Aspire.Tests/JasperFx.Aspire.Tests.csproj @@ -11,7 +11,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/JasperFx.Events.SourceGenerator.Tests/JasperFx.Events.SourceGenerator.Tests.csproj b/src/JasperFx.Events.SourceGenerator.Tests/JasperFx.Events.SourceGenerator.Tests.csproj index 1deb41c3..4acb5299 100644 --- a/src/JasperFx.Events.SourceGenerator.Tests/JasperFx.Events.SourceGenerator.Tests.csproj +++ b/src/JasperFx.Events.SourceGenerator.Tests/JasperFx.Events.SourceGenerator.Tests.csproj @@ -11,7 +11,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/JasperFx.SourceGenerator.Tests/JasperFx.SourceGenerator.Tests.csproj b/src/JasperFx.SourceGenerator.Tests/JasperFx.SourceGenerator.Tests.csproj index 0540ca50..e041b46c 100644 --- a/src/JasperFx.SourceGenerator.Tests/JasperFx.SourceGenerator.Tests.csproj +++ b/src/JasperFx.SourceGenerator.Tests/JasperFx.SourceGenerator.Tests.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/JasperFx/JasperFxOptions.cs b/src/JasperFx/JasperFxOptions.cs index 76f6d9f9..877731c3 100644 --- a/src/JasperFx/JasperFxOptions.cs +++ b/src/JasperFx/JasperFxOptions.cs @@ -22,8 +22,21 @@ public static bool HasReferenceToJasperFxTool(Assembly assembly) var names = assembly.GetReferencedAssemblies(); foreach (var name in names) { - var reference = Assembly.Load(name); - if (reference != null && reference.HasAttribute()) return true; + // Best-effort detection: an application's assembly graph routinely contains references + // that cannot be loaded or reflected over at runtime -- optional dependencies that were + // never deployed, assemblies trimmed away, or (as here) a reference whose own + // dependencies are missing from the output so that enumerating its custom attributes + // throws. None of that means the app is a JasperFx tool, and none of it is worth + // failing host startup over, so skip the assembly and keep looking. + try + { + var reference = Assembly.Load(name); + if (reference != null && reference.HasAttribute()) return true; + } + catch (Exception) + { + // Intentionally ignored; see above. + } } return false;