Files
novelly/tests/NovelSoftware.Tests/NovelSoftware.Tests.csproj
T
James WamplerandClaude Opus 5 30e0c6926e Migrate the test suite from xUnit + FluentAssertions to NUnit
All 44 tests, same names, same coverage — verified by diffing the runner's test
list before and after.

The load-bearing change is fixture lifecycle. xUnit builds a new test-class
instance per test, so a `readonly TestDatabase _db = new()` field gave every
test its own database. NUnit reuses one instance for the whole class, so those
field initialisers and constructors would have shared a single database across a
class and let tests read each other's rows. Setup moved into [SetUp]/[TearDown]
via a new ServiceTestFixture base class, which also collapses the per-class
service wiring that was duplicated five times.

Assertions are now Assert.That with the constraint model:

  Should().Be(x)              -> Is.EqualTo(x)
  Should().BeNull()           -> Is.Null
  Should().HaveCount(n)       -> Has.Count.EqualTo(n)
  Should().Equal(a, b)        -> Is.EqualTo(new[] { a, b })
  Should().BeEquivalentTo(..) -> Is.EquivalentTo(..)
  Should().Contain("x")       -> Does.Contain("x")
  Should().OnlyHaveUniqueItems() -> Is.Unique
  ThrowAsync<T>().WithMessage("*m*")
      -> Throws.TypeOf<T>().With.Message.Contains("m")

FluentAssertions' `.Which` chains became plain indexed asserts, grouped in
Assert.Multiple so a failure reports every broken expectation in the case rather
than stopping at the first.

Because a framework migration can quietly produce vacuously-passing tests,
spot-checked four conversions by mutation — breaking the code under an async
Assert.Multiple block, a sync one, a Throws constraint, and a collection
ordering assert. All four failed as they should, confirming the assertions are
live and that NUnit bound the async lambdas to AsyncTestDelegate rather than
silently accepting them as async void.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S56bfZMGe1hnhpWP4CjjNw
2026-08-06 12:11:20 -07:00

31 lines
1.1 KiB
XML

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="NUnit" Version="4.6.1" />
<PackageReference Include="NUnit.Analyzers" Version="4.14.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="NUnit3TestAdapter" Version="6.2.0" />
</ItemGroup>
<ItemGroup>
<Using Include="NUnit.Framework" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\NovelSoftware.Infrastructure\NovelSoftware.Infrastructure.csproj" />
<ProjectReference Include="..\..\src\NovelSoftware.Api\NovelSoftware.Api.csproj" />
</ItemGroup>
</Project>