From 35478bf1df71c6f19b78cb6c30e4faa90c7a8f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20=C5=81api=C5=84ski?= Date: Mon, 12 Oct 2026 22:34:25 +0200 Subject: [PATCH] test: replace FluentAssertions with xunit assertions FluentAssertions 8 is distributed under a commercial license, so the test projects now use the built-in xunit Assert API instead and the package is removed from central package management. --- src/Directory.Packages.props | 1 - .../ConcurrencyTestsBase.cs | 23 +++++--- .../RunWay.Storage.Tests.csproj | 1 - src/RunWay.Storage.Tests/StoreJobTestsBase.cs | 59 +++++++++---------- .../StoreRunnerTestsBase.cs | 29 +++++---- src/RunWay.Tests/RunWay.Tests.csproj | 1 - .../Unit/JobRunnerOptionsValidatorTests.cs | 11 ++-- src/RunWay.Tests/Unit/JobTests.cs | 54 ++++++++--------- .../Unit/NCrontabRecurrenceCalculatorTests.cs | 17 +++--- src/RunWay.Tests/Unit/PaginationTests.cs | 17 +++--- src/RunWay.Tests/Unit/SerializerTests.cs | 18 +++--- 11 files changed, 114 insertions(+), 117 deletions(-) diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 2f51e1a..b87841c 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -26,7 +26,6 @@ - diff --git a/src/RunWay.Storage.Tests/ConcurrencyTestsBase.cs b/src/RunWay.Storage.Tests/ConcurrencyTestsBase.cs index 29bb945..ffb8bde 100644 --- a/src/RunWay.Storage.Tests/ConcurrencyTestsBase.cs +++ b/src/RunWay.Storage.Tests/ConcurrencyTestsBase.cs @@ -1,4 +1,3 @@ -using FluentAssertions; using Kododo.RunWay.Core.Jobs; using Kododo.RunWay.Core.Runners; using Kododo.RunWay.Core.Store; @@ -67,8 +66,10 @@ public async Task MultipleRunners_AllJobsProcessedExactlyOnce() var remaining = await Store.GetCountAsync( new JobsFilter { Statuses = [JobStatus.Scheduled, JobStatus.Running] }, CancellationToken.None); - succeeded.Should().Be(jobCount, "each job should be processed exactly once"); - remaining.Should().Be(0, "no job should remain unprocessed"); + // each job should be processed exactly once + Assert.Equal(jobCount, succeeded); + // no job should remain unprocessed + Assert.Equal(0, remaining); } [Fact] @@ -107,12 +108,14 @@ async Task RaceAsync(RunnerInfo runnerInfo) var results = await Task.WhenAll(RaceAsync(runnerInfo1), RaceAsync(runnerInfo2)); - results.Count(r => r).Should().Be(1, "exactly one runner should win the race"); - results.Count(r => !r).Should().Be(1, "the other runner should get ConcurrencyException"); + // exactly one runner should win the race + Assert.Equal(1, results.Count(r => r)); + // the other runner should get ConcurrencyException + Assert.Equal(1, results.Count(r => !r)); var count = await Store.GetCountAsync( new JobsFilter { Statuses = [JobStatus.Succeeded] }, CancellationToken.None); - count.Should().Be(1); + Assert.Equal(1, count); } [Fact] @@ -164,7 +167,8 @@ public async Task MultipleThreadsPerRunner_WithSemaphore_AllJobsProcessed() var succeeded = await Store.GetCountAsync( new JobsFilter { Statuses = [JobStatus.Succeeded] }, CancellationToken.None); - succeeded.Should().Be(jobCount, "the semaphore should prevent double-fetching of a job"); + // the semaphore should prevent double-fetching of a job + Assert.Equal(jobCount, succeeded); } [Fact] @@ -188,7 +192,7 @@ public async Task HighLoad_ManyRunners_ManyJobs_AllJobsSucceed() var succeededCount = await Store.GetCountAsync( new JobsFilter { Statuses = [JobStatus.Succeeded] }, CancellationToken.None); - succeededCount.Should().Be(jobCount); + Assert.Equal(jobCount, succeededCount); } [Fact] @@ -239,6 +243,7 @@ await Task.WhenAll( var succeededCount = await Store.GetCountAsync( new JobsFilter { Statuses = [JobStatus.Succeeded] }, CancellationToken.None); - succeededCount.Should().Be(10, "each runner should process its 5 jobs"); + // each runner should process its 5 jobs + Assert.Equal(10, succeededCount); } } diff --git a/src/RunWay.Storage.Tests/RunWay.Storage.Tests.csproj b/src/RunWay.Storage.Tests/RunWay.Storage.Tests.csproj index 194d655..21b96fc 100644 --- a/src/RunWay.Storage.Tests/RunWay.Storage.Tests.csproj +++ b/src/RunWay.Storage.Tests/RunWay.Storage.Tests.csproj @@ -8,7 +8,6 @@ - diff --git a/src/RunWay.Storage.Tests/StoreJobTestsBase.cs b/src/RunWay.Storage.Tests/StoreJobTestsBase.cs index 4dbd03b..c182334 100644 --- a/src/RunWay.Storage.Tests/StoreJobTestsBase.cs +++ b/src/RunWay.Storage.Tests/StoreJobTestsBase.cs @@ -1,4 +1,3 @@ -using FluentAssertions; using Kododo.RunWay.Core.Jobs; using Kododo.RunWay.Core.Jobs.Audit; using Kododo.RunWay.Core.Runners; @@ -26,7 +25,7 @@ public override async Task InitializeAsync() public async Task CreateAsync_ReturnsNonEmptyJobId() { var job = await Store.CreateAsync(NewJob(), CancellationToken.None); - job.Id.Value.Should().NotBeNullOrEmpty(); + Assert.False(string.IsNullOrEmpty(job.Id.Value)); } [Fact] @@ -35,8 +34,8 @@ public async Task CreateAsync_PersistedJobCanBeFound() var job = await Store.CreateAsync(NewJob(), CancellationToken.None); var found = await Store.FindAsync(job.Id, CancellationToken.None); - found.Should().NotBeNull(); - found.Id.Should().Be(job.Id); + Assert.NotNull(found); + Assert.Equal(job.Id, found.Id); } [Fact] @@ -45,8 +44,8 @@ public async Task CreateAsync_CreatesAuditRecords() var job = await Store.CreateAsync(NewJob(), CancellationToken.None); var details = await Store.GetDetailsAsync(job.Id, CancellationToken.None); - details.Audit.Should().Contain(a => a.Type == JobAuditRecordType.Created); - details.Audit.Should().Contain(a => a.Type == JobAuditRecordType.Scheduled); + Assert.Contains(details.Audit, a => a.Type == JobAuditRecordType.Created); + Assert.Contains(details.Audit, a => a.Type == JobAuditRecordType.Scheduled); } [Fact] @@ -59,14 +58,14 @@ public async Task CreateAsync_PersistsJobData() var found = await Store.FindAsync(job.Id, CancellationToken.None); - found!.Data.Type.Should().Be("MyJobType"); + Assert.Equal("MyJobType", found!.Data.Type); } [Fact] public async Task FindAsync_WhenJobDoesNotExist_ReturnsNull() { var result = await Store.FindAsync(new JobId("999999"), CancellationToken.None); - result.Should().BeNull(); + Assert.Null(result); } [Fact] @@ -78,7 +77,7 @@ public async Task UpdateAsync_ChangesJobStatus() await Store.UpdateAsync(job, CancellationToken.None); var updated = await Store.FindAsync(job.Id, CancellationToken.None); - updated!.Status.Should().Be(JobStatus.Running); + Assert.Equal(JobStatus.Running, updated!.Status); } [Fact] @@ -90,7 +89,7 @@ public async Task UpdateAsync_SavesAuditRecords() await Store.UpdateAsync(job, CancellationToken.None); var details = await Store.GetDetailsAsync(job.Id, CancellationToken.None); - details.Audit.Should().Contain(a => a.Type == JobAuditRecordType.Started); + Assert.Contains(details.Audit, a => a.Type == JobAuditRecordType.Started); } [Fact] @@ -106,7 +105,7 @@ public async Task UpdateAsync_Started_Succeeded_StatusIsSucceeded() await Store.UpdateAsync(running, CancellationToken.None); var result = await Store.FindAsync(job.Id, CancellationToken.None); - result!.Status.Should().Be(JobStatus.Succeeded); + Assert.Equal(JobStatus.Succeeded, result!.Status); } [Fact] @@ -119,8 +118,8 @@ public async Task GetManyAsync_ReturnsPaginatedResults() new JobsQuery { Pagination = new Pagination(1, 3) }, CancellationToken.None); - result.Items.Should().HaveCount(3); - result.TotalItems.Should().Be(5); + Assert.Equal(3, result.Items.Count); + Assert.Equal(5, result.TotalItems); } [Fact] @@ -133,7 +132,7 @@ public async Task GetManyAsync_SecondPage_ReturnsRemainingItems() new JobsQuery { Pagination = new Pagination(2, 3) }, CancellationToken.None); - result.Items.Should().HaveCount(2); + Assert.Equal(2, result.Items.Count); } [Fact] @@ -151,8 +150,8 @@ public async Task GetManyAsync_FiltersByStatus() Filter = new JobsFilter { Statuses = [JobStatus.Running] } }, CancellationToken.None); - result.Items.Should().ContainSingle(); - result.Items.Single().Status.Should().Be(JobStatus.Running); + Assert.Single(result.Items); + Assert.Equal(JobStatus.Running, result.Items.Single().Status); } [Fact] @@ -167,7 +166,7 @@ public async Task GetManyAsync_FiltersByMaxScheduledAt_ExcludesFuture() Filter = new JobsFilter { MaxScheduledAt = DateTimeOffset.UtcNow } }, CancellationToken.None); - result.Items.Should().ContainSingle(); + Assert.Single(result.Items); } [Fact] @@ -177,7 +176,7 @@ public async Task GetCountAsync_ReturnsCorrectCount() await Store.CreateAsync(NewJob(), CancellationToken.None); var count = await Store.GetCountAsync(new JobsFilter(), CancellationToken.None); - count.Should().Be(2); + Assert.Equal(2, count); } [Fact] @@ -193,7 +192,7 @@ public async Task GetCountAsync_FiltersByStatus() new JobsFilter { Statuses = [JobStatus.Scheduled] }, CancellationToken.None); - count.Should().Be(1); + Assert.Equal(1, count); } [Fact] @@ -205,10 +204,10 @@ public async Task GetDetailsAsync_ReturnsJobWithFullAuditTrail() var details = await Store.GetDetailsAsync(job.Id, CancellationToken.None); - details.Id.Should().Be(job.Id); - details.Audit.Should().Contain(a => a.Type == JobAuditRecordType.Created); - details.Audit.Should().Contain(a => a.Type == JobAuditRecordType.Scheduled); - details.Audit.Should().Contain(a => a.Type == JobAuditRecordType.Started); + Assert.Equal(job.Id, details.Id); + Assert.Contains(details.Audit, a => a.Type == JobAuditRecordType.Created); + Assert.Contains(details.Audit, a => a.Type == JobAuditRecordType.Scheduled); + Assert.Contains(details.Audit, a => a.Type == JobAuditRecordType.Started); } [Fact] @@ -221,8 +220,8 @@ public async Task GetOneOrDefaultAsync_ReturnsJobMatchingFilter() Filter = new JobsFilter { Statuses = [JobStatus.Scheduled] } }, CancellationToken.None); - result.Should().NotBeNull(); - result.Id.Should().Be(job.Id); + Assert.NotNull(result); + Assert.Equal(job.Id, result.Id); } [Fact] @@ -233,7 +232,7 @@ public async Task GetOneOrDefaultAsync_WhenNoMatch_ReturnsNull() Filter = new JobsFilter { Statuses = [JobStatus.Failed] } }, CancellationToken.None); - result.Should().BeNull(); + Assert.Null(result); } [Fact] @@ -248,8 +247,8 @@ public async Task Failed_WithRetries_ReschedulesJobInStore() await Store.UpdateAsync(running, CancellationToken.None); var result = await Store.FindAsync(job.Id, CancellationToken.None); - result!.Status.Should().Be(JobStatus.Scheduled); - result.RetriesCount.Should().Be(1); + Assert.Equal(JobStatus.Scheduled, result!.Status); + Assert.Equal(1, result.RetriesCount); } [Fact] @@ -261,7 +260,7 @@ public async Task DataPersistedAcrossStoreInstances() var freshStore = freshScope.ServiceProvider.GetRequiredService(); var result = await freshStore.FindAsync(job.Id, CancellationToken.None); - result.Should().NotBeNull(); - result.Id.Should().Be(job.Id); + Assert.NotNull(result); + Assert.Equal(job.Id, result.Id); } } diff --git a/src/RunWay.Storage.Tests/StoreRunnerTestsBase.cs b/src/RunWay.Storage.Tests/StoreRunnerTestsBase.cs index 8984aaf..41fe3c6 100644 --- a/src/RunWay.Storage.Tests/StoreRunnerTestsBase.cs +++ b/src/RunWay.Storage.Tests/StoreRunnerTestsBase.cs @@ -1,4 +1,3 @@ -using FluentAssertions; using Kododo.RunWay.Core.Runners; using Xunit; @@ -13,7 +12,7 @@ protected StoreRunnerTestsBase(TFixture fixture) : base(fixture) { } public async Task RegisterRunnerAsync_ReturnsNonEmptyRunnerId() { var runnerId = await Store.RegisterRunnerAsync("runner-1", ["JobA"], DateTimeOffset.UtcNow.AddMinutes(1), CancellationToken.None); - runnerId.Value.Should().NotBeNullOrEmpty(); + Assert.False(string.IsNullOrEmpty(runnerId.Value)); } [Fact] @@ -23,7 +22,7 @@ public async Task RegisterRunnerAsync_RunnerAppearsInGetAll() var runners = await Store.GetAllRunnersAsync(CancellationToken.None); - runners.Should().ContainSingle(r => r.Id == runnerId); + Assert.Single(runners, r => r.Id == runnerId); } [Fact] @@ -33,14 +32,14 @@ public async Task RegisterRunnerAsync_PersistsName() var runners = await Store.GetAllRunnersAsync(CancellationToken.None); - runners.Should().ContainSingle(r => r.Name == "my-runner"); + Assert.Single(runners, r => r.Name == "my-runner"); } [Fact] public async Task GetAllRunnersAsync_WhenNoRunners_ReturnsEmpty() { var runners = await Store.GetAllRunnersAsync(CancellationToken.None); - runners.Should().BeEmpty(); + Assert.Empty(runners); } [Fact] @@ -51,8 +50,8 @@ public async Task GetAllRunnersAsync_ReturnsAllRegisteredRunners() var runners = await Store.GetAllRunnersAsync(CancellationToken.None); - runners.Should().HaveCount(2); - runners.Select(r => r.Name).Should().BeEquivalentTo("runner-1", "runner-2"); + Assert.Equal(2, runners.Count); + Assert.Equal(new[] { "runner-1", "runner-2" }, runners.Select(r => r.Name).Order(StringComparer.Ordinal)); } [Fact] @@ -62,7 +61,7 @@ public async Task GetAllRunnersAsync_RecentlyRegisteredRunner_IsOnline() var runners = await Store.GetAllRunnersAsync(CancellationToken.None); - runners.Single().Status.Should().Be(RunnerStatus.Online); + Assert.Equal(RunnerStatus.Online, runners.Single().Status); } [Fact] @@ -71,7 +70,7 @@ public async Task KeepAliveAsync_DoesNotThrow() var runnerId = await Store.RegisterRunnerAsync("runner-1", ["JobA"], DateTimeOffset.UtcNow.AddMinutes(1), CancellationToken.None); var act = async () => await Store.KeepAliveAsync(runnerId, DateTimeOffset.UtcNow.AddMinutes(1), CancellationToken.None); - await act.Should().NotThrowAsync(); + Assert.Null(await Record.ExceptionAsync(act)); } [Fact] @@ -81,7 +80,7 @@ public async Task RemoveRunnerAsync_RunnerNoLongerInGetAll() await Store.RemoveRunnerAsync(runnerId, CancellationToken.None); var runners = await Store.GetAllRunnersAsync(CancellationToken.None); - runners.Should().NotContain(r => r.Id == runnerId); + Assert.DoesNotContain(runners, r => r.Id == runnerId); } [Fact] @@ -93,7 +92,7 @@ public async Task RemoveRunnerAsync_OtherRunnersNotAffected() await Store.RemoveRunnerAsync(runnerId1, CancellationToken.None); var runners = await Store.GetAllRunnersAsync(CancellationToken.None); - runners.Should().ContainSingle(r => r.Id == runnerId2); + Assert.Single(runners, r => r.Id == runnerId2); } [Fact] @@ -103,7 +102,7 @@ public async Task GetRunnerDetailsAsync_ReturnsCorrectName() var details = await Store.GetRunnerDetailsAsync(runnerId, CancellationToken.None); - details.Name.Should().Be("details-runner"); + Assert.Equal("details-runner", details.Name); } [Fact] @@ -113,7 +112,7 @@ public async Task GetRunnerDetailsAsync_ReturnsRegisteredJobTypes() var details = await Store.GetRunnerDetailsAsync(runnerId, CancellationToken.None); - details.JobTypes.Should().BeEquivalentTo("JobA", "JobB"); + Assert.Equal(new[] { "JobA", "JobB" }, details.JobTypes.Order(StringComparer.Ordinal)); } [Fact] @@ -123,13 +122,13 @@ public async Task GetRunnerDetailsAsync_InitiallyHasNoJobs() var details = await Store.GetRunnerDetailsAsync(runnerId, CancellationToken.None); - details.Jobs.Should().BeEmpty(); + Assert.Empty(details.Jobs); } [Fact] public async Task InitializeAsync_WhenCalledTwice_IsIdempotent() { var act = async () => await Store.InitializeAsync(CancellationToken.None); - await act.Should().NotThrowAsync(); + Assert.Null(await Record.ExceptionAsync(act)); } } diff --git a/src/RunWay.Tests/RunWay.Tests.csproj b/src/RunWay.Tests/RunWay.Tests.csproj index 0163109..e2197ba 100644 --- a/src/RunWay.Tests/RunWay.Tests.csproj +++ b/src/RunWay.Tests/RunWay.Tests.csproj @@ -14,7 +14,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/src/RunWay.Tests/Unit/JobRunnerOptionsValidatorTests.cs b/src/RunWay.Tests/Unit/JobRunnerOptionsValidatorTests.cs index 1fa8275..b1fcd78 100644 --- a/src/RunWay.Tests/Unit/JobRunnerOptionsValidatorTests.cs +++ b/src/RunWay.Tests/Unit/JobRunnerOptionsValidatorTests.cs @@ -1,4 +1,3 @@ -using FluentAssertions; using Kododo.RunWay.Runner; using Xunit; @@ -13,7 +12,7 @@ public void Validate_WhenThreadsCountIsZero_Fails() { var options = new JobRunnerOptions { ThreadsCount = 0 }; var result = _validator.Validate(null, options); - result.Failed.Should().BeTrue(); + Assert.True(result.Failed); } [Fact] @@ -21,7 +20,7 @@ public void Validate_WhenThreadsCountIsNegative_Fails() { var options = new JobRunnerOptions { ThreadsCount = -1 }; var result = _validator.Validate(null, options); - result.Failed.Should().BeTrue(); + Assert.True(result.Failed); } [Fact] @@ -29,7 +28,7 @@ public void Validate_WhenThreadsCountIsPositive_Succeeds() { var options = new JobRunnerOptions { ThreadsCount = 4 }; var result = _validator.Validate(null, options); - result.Succeeded.Should().BeTrue(); + Assert.True(result.Succeeded); } [Fact] @@ -37,7 +36,7 @@ public void Validate_WhenThreadsCountIsOne_Succeeds() { var options = new JobRunnerOptions { ThreadsCount = 1 }; var result = _validator.Validate(null, options); - result.Succeeded.Should().BeTrue(); + Assert.True(result.Succeeded); } [Fact] @@ -45,6 +44,6 @@ public void Validate_WhenFailed_FailureMessageMentionsThreadsCount() { var options = new JobRunnerOptions { ThreadsCount = 0 }; var result = _validator.Validate(null, options); - result.FailureMessage.Should().Contain(nameof(JobRunnerOptions.ThreadsCount)); + Assert.Contains(nameof(JobRunnerOptions.ThreadsCount), result.FailureMessage); } } diff --git a/src/RunWay.Tests/Unit/JobTests.cs b/src/RunWay.Tests/Unit/JobTests.cs index 88c9da6..3a6d48b 100644 --- a/src/RunWay.Tests/Unit/JobTests.cs +++ b/src/RunWay.Tests/Unit/JobTests.cs @@ -1,4 +1,3 @@ -using FluentAssertions; using Kododo.RunWay.Core.Jobs; using Kododo.RunWay.Core.Jobs.Audit; using Kododo.RunWay.Core.Runners; @@ -25,22 +24,23 @@ private static Job NewRunning(IReadOnlyList? retryDelays = null) public void CreateNew_SetsStatusToScheduled() { var job = NewScheduled(); - job.Status.Should().Be(JobStatus.Scheduled); + Assert.Equal(JobStatus.Scheduled, job.Status); } [Fact] public void CreateNew_RunnerId_IsNull() { var job = NewScheduled(); - job.RunnerId.Should().BeNull(); + Assert.Null(job.RunnerId); } [Fact] public void CreateNew_AddsPendingCreatedAndScheduledAuditEvents() { var job = NewScheduled(); - job.PendingEvents.Select(e => e.Type) - .Should().BeEquivalentTo([JobAuditRecordType.Created, JobAuditRecordType.Scheduled]); + Assert.Equal( + new[] { JobAuditRecordType.Created, JobAuditRecordType.Scheduled }.Order(), + job.PendingEvents.Select(e => e.Type).Order()); } [Fact] @@ -48,7 +48,7 @@ public void Started_SetsStatusToRunning() { var job = NewScheduled(); job.Started(SampleRunner); - job.Status.Should().Be(JobStatus.Running); + Assert.Equal(JobStatus.Running, job.Status); } [Fact] @@ -56,7 +56,7 @@ public void Started_SetsRunnerId() { var job = NewScheduled(); job.Started(SampleRunner); - job.RunnerId.Should().Be(SampleRunner.Id); + Assert.Equal(SampleRunner.Id, job.RunnerId); } [Fact] @@ -64,7 +64,7 @@ public void Started_AddsStartedAuditEvent() { var job = NewScheduled(); job.Started(SampleRunner); - job.PendingEvents.Should().Contain(e => e.Type == JobAuditRecordType.Started); + Assert.Contains(job.PendingEvents, e => e.Type == JobAuditRecordType.Started); } [Fact] @@ -72,7 +72,7 @@ public void Started_WhenAlreadyRunning_Throws() { var job = NewRunning(); var act = () => job.Started(SampleRunner); - act.Should().Throw(); + Assert.ThrowsAny(act); } [Fact] @@ -82,7 +82,7 @@ public void Started_WhenJobHasRunnerId_Throws() job.Started(SampleRunner); var act = () => job.Started(SampleRunner); - act.Should().Throw(); + Assert.ThrowsAny(act); } [Fact] @@ -90,7 +90,7 @@ public void Succeeded_SetsStatusToSucceeded() { var job = NewRunning(); job.Succeeded(); - job.Status.Should().Be(JobStatus.Succeeded); + Assert.Equal(JobStatus.Succeeded, job.Status); } [Fact] @@ -98,7 +98,7 @@ public void Succeeded_ClearsRunnerId() { var job = NewRunning(); job.Succeeded(); - job.RunnerId.Should().BeNull(); + Assert.Null(job.RunnerId); } [Fact] @@ -106,7 +106,7 @@ public void Succeeded_AddsSucceededAuditEvent() { var job = NewRunning(); job.Succeeded(); - job.PendingEvents.Should().Contain(e => e.Type == JobAuditRecordType.Succeeded); + Assert.Contains(job.PendingEvents, e => e.Type == JobAuditRecordType.Succeeded); } [Fact] @@ -114,7 +114,7 @@ public void Succeeded_WhenNotRunning_Throws() { var job = NewScheduled(); var act = () => job.Succeeded(); - act.Should().Throw(); + Assert.ThrowsAny(act); } [Fact] @@ -122,7 +122,7 @@ public void Failed_WhenNoRetriesLeft_SetsStatusToFailed() { var job = NewRunning(retryDelays: []); job.Failed("error"); - job.Status.Should().Be(JobStatus.Failed); + Assert.Equal(JobStatus.Failed, job.Status); } [Fact] @@ -130,7 +130,7 @@ public void Failed_WhenNoRetriesLeft_ClearsRunnerId() { var job = NewRunning(retryDelays: []); job.Failed("error"); - job.RunnerId.Should().BeNull(); + Assert.Null(job.RunnerId); } [Fact] @@ -138,7 +138,7 @@ public void Failed_WhenRetriesLeft_ReschedulesJob() { var job = NewRunning(retryDelays: [10, 60]); job.Failed("error"); - job.Status.Should().Be(JobStatus.Scheduled); + Assert.Equal(JobStatus.Scheduled, job.Status); } [Fact] @@ -146,7 +146,7 @@ public void Failed_WhenRetriesLeft_IncrementsRetriesCount() { var job = NewRunning(retryDelays: [10, 60]); job.Failed("error"); - job.RetriesCount.Should().Be(1); + Assert.Equal(1, job.RetriesCount); } [Fact] @@ -154,7 +154,7 @@ public void Failed_WhenRetriesLeft_AddsScheduledAuditEvent() { var job = NewRunning(retryDelays: [10]); job.Failed("error"); - job.PendingEvents.Should().Contain(e => e.Type == JobAuditRecordType.Scheduled); + Assert.Contains(job.PendingEvents, e => e.Type == JobAuditRecordType.Scheduled); } [Fact] @@ -166,7 +166,7 @@ public void Failed_WhenAllRetriesExhausted_SetsStatusToFailed() job.Started(SampleRunner); job.Failed("second failure"); - job.Status.Should().Be(JobStatus.Failed); + Assert.Equal(JobStatus.Failed, job.Status); } [Fact] @@ -174,7 +174,7 @@ public void Failed_WhenNotRunning_Throws() { var job = NewScheduled(); var act = () => job.Failed("error"); - act.Should().Throw(); + Assert.ThrowsAny(act); } [Fact] @@ -183,7 +183,7 @@ public void Requeue_SetsStatusToScheduled() var job = NewRunning(retryDelays: []); job.Failed("error"); job.Requeue(); - job.Status.Should().Be(JobStatus.Scheduled); + Assert.Equal(JobStatus.Scheduled, job.Status); } [Fact] @@ -193,7 +193,7 @@ public void Requeue_IncrementsRetriesCount() job.Failed("error"); var countBefore = job.RetriesCount; job.Requeue(); - job.RetriesCount.Should().Be(countBefore + 1); + Assert.Equal(countBefore + 1, job.RetriesCount); } [Fact] @@ -202,7 +202,7 @@ public void Requeue_ClearsRunnerId() var job = NewRunning(retryDelays: []); job.Failed("error"); job.Requeue(); - job.RunnerId.Should().BeNull(); + Assert.Null(job.RunnerId); } [Fact] @@ -211,7 +211,7 @@ public void Requeue_AddsScheduledAuditEvent() var job = NewRunning(retryDelays: []); job.Failed("error"); job.Requeue(); - job.PendingEvents.Should().Contain(e => e.Type == JobAuditRecordType.Scheduled); + Assert.Contains(job.PendingEvents, e => e.Type == JobAuditRecordType.Scheduled); } [Fact] @@ -219,7 +219,7 @@ public void Requeue_WhenNotFailed_Throws() { var job = NewScheduled(); var act = () => job.Requeue(); - act.Should().Throw(); + Assert.ThrowsAny(act); } [Fact] @@ -227,6 +227,6 @@ public void Requeue_WhenRunning_Throws() { var job = NewRunning(); var act = () => job.Requeue(); - act.Should().Throw(); + Assert.ThrowsAny(act); } } diff --git a/src/RunWay.Tests/Unit/NCrontabRecurrenceCalculatorTests.cs b/src/RunWay.Tests/Unit/NCrontabRecurrenceCalculatorTests.cs index 9a257d8..5e7cba6 100644 --- a/src/RunWay.Tests/Unit/NCrontabRecurrenceCalculatorTests.cs +++ b/src/RunWay.Tests/Unit/NCrontabRecurrenceCalculatorTests.cs @@ -1,4 +1,3 @@ -using FluentAssertions; using Xunit; namespace Kododo.RunWay.Tests.Unit; @@ -12,7 +11,7 @@ public void CalculateNextOccurrence_WithStandardExpression_ReturnsFutureDate() { var from = new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero); var result = _calculator.CalculateNextOccurrence("0 * * * *", from); - result.Should().BeAfter(from); + Assert.True(result > from, $"Expected {result:O} to be after {from:O}."); } [Fact] @@ -20,7 +19,7 @@ public void CalculateNextOccurrence_WithStepExpression_ReturnsFutureDate() { var from = new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero); var result = _calculator.CalculateNextOccurrence("*/5 * * * *", from); - result.Should().BeAfter(from); + Assert.True(result > from, $"Expected {result:O} to be after {from:O}."); } [Fact] @@ -28,7 +27,7 @@ public void CalculateNextOccurrence_WithStepExpression_ReturnsCorrectInterval() { var from = new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero); var result = _calculator.CalculateNextOccurrence("*/5 * * * *", from); - result.Minute.Should().Be(5); + Assert.Equal(5, result.Minute); } [Fact] @@ -36,7 +35,7 @@ public void CalculateNextOccurrence_WithMidMinute_ReturnsNextSlot() { var from = new DateTimeOffset(2024, 1, 1, 12, 3, 0, TimeSpan.Zero); var result = _calculator.CalculateNextOccurrence("*/5 * * * *", from); - result.Minute.Should().Be(5); + Assert.Equal(5, result.Minute); } [Fact] @@ -44,8 +43,8 @@ public void CalculateNextOccurrence_WithHourlyExpression_AdvancesHour() { var from = new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero); var result = _calculator.CalculateNextOccurrence("0 * * * *", from); - result.Hour.Should().Be(13); - result.Minute.Should().Be(0); + Assert.Equal(13, result.Hour); + Assert.Equal(0, result.Minute); } [Fact] @@ -53,7 +52,7 @@ public void CalculateNextOccurrence_WithInvalidExpression_Throws() { var from = DateTimeOffset.UtcNow; var act = () => _calculator.CalculateNextOccurrence("not a cron", from); - act.Should().Throw(); + Assert.ThrowsAny(() => act()); } [Fact] @@ -61,6 +60,6 @@ public void CalculateNextOccurrence_ResultIsUtc() { var from = new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero); var result = _calculator.CalculateNextOccurrence("*/5 * * * *", from); - result.Offset.Should().Be(TimeSpan.Zero); + Assert.Equal(TimeSpan.Zero, result.Offset); } } diff --git a/src/RunWay.Tests/Unit/PaginationTests.cs b/src/RunWay.Tests/Unit/PaginationTests.cs index 3d2e447..979dfe1 100644 --- a/src/RunWay.Tests/Unit/PaginationTests.cs +++ b/src/RunWay.Tests/Unit/PaginationTests.cs @@ -1,4 +1,3 @@ -using FluentAssertions; using Kododo.RunWay.Core.Store.Queries; using Xunit; @@ -10,49 +9,49 @@ public class PaginationTests public void Pagination_WhenPageIsZero_Throws() { var act = () => new Pagination(0); - act.Should().Throw(); + Assert.ThrowsAny(act); } [Fact] public void Pagination_WhenPageIsNegative_Throws() { var act = () => new Pagination(-1); - act.Should().Throw(); + Assert.ThrowsAny(act); } [Fact] public void Pagination_WhenPageSizeIsZero_Throws() { var act = () => new Pagination(1, 0); - act.Should().Throw(); + Assert.ThrowsAny(act); } [Fact] public void Pagination_WhenPageSizeIsNegative_Throws() { var act = () => new Pagination(1, -5); - act.Should().Throw(); + Assert.ThrowsAny(act); } [Fact] public void Pagination_WhenValid_DoesNotThrow() { var act = () => new Pagination(1); - act.Should().NotThrow(); + Assert.Null(Record.Exception(act)); } [Fact] public void Pagination_WhenValid_SetsProperties() { var pagination = new Pagination(3, 50); - pagination.Page.Should().Be(3); - pagination.PageSize.Should().Be(50); + Assert.Equal(3, pagination.Page); + Assert.Equal(50, pagination.PageSize); } [Fact] public void Pagination_DefaultPageSize_IsTwenty() { var pagination = new Pagination(1); - pagination.PageSize.Should().Be(20); + Assert.Equal(20, pagination.PageSize); } } diff --git a/src/RunWay.Tests/Unit/SerializerTests.cs b/src/RunWay.Tests/Unit/SerializerTests.cs index bc4289d..a02c603 100644 --- a/src/RunWay.Tests/Unit/SerializerTests.cs +++ b/src/RunWay.Tests/Unit/SerializerTests.cs @@ -1,4 +1,3 @@ -using FluentAssertions; using Kododo.RunWay.Core.Serialization; using Xunit; @@ -14,14 +13,15 @@ private record SamplePayload(string Name, int Value); public void Serialize_ReturnsJobDataWithCorrectType() { var result = _serializer.Serialize(new SamplePayload("test", 42)); - result.Type.Should().Be(typeof(SamplePayload).FullName); + Assert.Equal(typeof(SamplePayload).FullName, result.Type); } [Fact] public void Serialize_ReturnsJobDataWithSerializedJson() { var result = _serializer.Serialize(new SamplePayload("test", 42)); - result.Data.Should().Contain("test").And.Contain("42"); + Assert.Contains("test", result.Data); + Assert.Contains("42", result.Data); } [Fact] @@ -30,9 +30,9 @@ public void Deserialize_ReturnsCorrectObject() var jobData = _serializer.Serialize(new SamplePayload("hello", 99)); var result = _serializer.Deserialize(jobData); - result.Should().BeOfType(); - ((SamplePayload)result).Name.Should().Be("hello"); - ((SamplePayload)result).Value.Should().Be(99); + Assert.IsType(result); + Assert.Equal("hello", ((SamplePayload)result).Name); + Assert.Equal(99, ((SamplePayload)result).Value); } [Fact] @@ -40,7 +40,7 @@ public void Deserialize_WhenTypeNotFound_Throws() { var jobData = new Core.Jobs.JobData("NonExistent.Type.That.DoesNotExist", "{}"); var act = () => _serializer.Deserialize(jobData); - act.Should().Throw(); + Assert.ThrowsAny(act); } [Fact] @@ -50,13 +50,13 @@ public void SerializeDeserialize_RoundTrip_PreservesAllProperties() var jobData = _serializer.Serialize(original); var result = (SamplePayload)_serializer.Deserialize(jobData); - result.Should().Be(original); + Assert.Equal(original, result); } [Fact] public void SerializeType_ReturnsFullName() { var result = _serializer.SerializeType(typeof(SamplePayload)); - result.Should().Be(typeof(SamplePayload).FullName); + Assert.Equal(typeof(SamplePayload).FullName, result); } }