Skip to content

Commit ef8e766

Browse files
thomhurstclaude
andauthored
test: improve test module return types and document external URL dependency (#1673)
- Change test modules from IDictionary<string, object>? to bool when no meaningful return value is needed (Issue #1597). Using bool return type is cleaner and more explicit than returning null for nullable dictionaries. - Add documentation comment to DownloaderTests explaining the external URL dependency and why this approach is reasonable for testing real download functionality (Issue #1619). - Keep IDictionary<string, object> (non-nullable) for JsonSerializationTests where actual dictionary values are needed for testing serialization. - Use string return type for FailedModuleWithCustomRetryPolicy to work with the IRetryable<T> interface (value types have issues with T? generics). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent fdf253f commit ef8e766

26 files changed

Lines changed: 248 additions & 242 deletions

test/ModularPipelines.UnitTests/AfterPipelineLoggerTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ namespace ModularPipelines.UnitTests;
1010

1111
public class AfterPipelineLoggerTests
1212
{
13-
private class AfterPipelineLoggingModule : Module<IDictionary<string, object>?>
13+
private class AfterPipelineLoggingModule : Module<bool>
1414
{
15-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
15+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
1616
{
1717
context.LogOnPipelineEnd("Blah!");
1818
await Task.CompletedTask;
19-
return null;
19+
return true;
2020
}
2121
}
2222

23-
private class AfterPipelineLoggingWithExceptionModule : Module<IDictionary<string, object>?>
23+
private class AfterPipelineLoggingWithExceptionModule : Module<bool>
2424
{
25-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
25+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
2626
{
2727
context.LogOnPipelineEnd("Blah!");
2828
await Task.CompletedTask;

test/ModularPipelines.UnitTests/AlwaysRunTests.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,39 @@ namespace ModularPipelines.UnitTests;
1313

1414
public class AlwaysRunTests : TestBase
1515
{
16-
public class MyModule1 : Module<IDictionary<string, object>?>
16+
public class MyModule1 : Module<bool>
1717
{
18-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
18+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
1919
{
2020
await Task.Yield();
2121
throw new Exception();
2222
}
2323
}
2424

2525
[ModularPipelines.Attributes.DependsOn<MyModule1>]
26-
public class MyModule2 : Module<IDictionary<string, object>?>, IAlwaysRun
26+
public class MyModule2 : Module<bool>, IAlwaysRun
2727
{
28-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
28+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
2929
{
3030
await Task.Yield();
3131
throw new Exception();
3232
}
3333
}
3434

3535
[ModularPipelines.Attributes.DependsOn<MyModule2>]
36-
public class MyModule3 : Module<IDictionary<string, object>?>, IAlwaysRun
36+
public class MyModule3 : Module<bool>, IAlwaysRun
3737
{
38-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
38+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
3939
{
4040
await Task.Yield();
4141
throw new Exception();
4242
}
4343
}
4444

4545
[ModularPipelines.Attributes.DependsOn<MyModule3>]
46-
public class MyModule4 : Module<IDictionary<string, object>?>, IAlwaysRun
46+
public class MyModule4 : Module<bool>, IAlwaysRun
4747
{
48-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
48+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
4949
{
5050
await Task.Yield();
5151
throw new Exception();

test/ModularPipelines.UnitTests/AsyncDisposableModuleTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ public async Task SuccessfullyDisposed()
1515
await Assert.That(pipelineSummary.Modules.OfType<AsyncDisposableModule>().Single().IsDisposed).IsTrue();
1616
}
1717

18-
public class AsyncDisposableModule : Module<IDictionary<string, object>?>, IAsyncDisposable
18+
public class AsyncDisposableModule : Module<bool>, IAsyncDisposable
1919
{
2020
public bool IsDisposed { get; private set; }
2121

2222
/// <inheritdoc/>
23-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
23+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
2424
{
2525
// Reduced delay from 100ms to 1ms for faster test execution
2626
await Task.Delay(1, cancellationToken);
27-
return null;
27+
return true;
2828
}
2929

3030
/// <inheritdoc/>

test/ModularPipelines.UnitTests/DependsOnAllInheritingFromTests.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ public class DependsOnAllInheritingFromTests : TestBase
1313
{
1414
private static readonly TimeSpan ModuleDelay = TimeSpan.FromMilliseconds(50);
1515

16-
private abstract class BaseModule : Module<IDictionary<string, object>?>
16+
private abstract class BaseModule : Module<bool>
1717
{
18-
public abstract override Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken);
18+
public abstract override Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken);
1919
}
2020

2121
// Generic base module for testing open generic type dependencies (Issue #1337)
@@ -52,40 +52,40 @@ public override async Task<bool> ExecuteAsync(IModuleContext context, Cancellati
5252

5353
private class Module1 : BaseModule
5454
{
55-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
55+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
5656
{
5757
await Task.Delay(ModuleDelay, cancellationToken);
58-
return null;
58+
return true;
5959
}
6060
}
6161

6262
[ModularPipelines.Attributes.DependsOn<Module1>]
6363
private class Module2 : BaseModule
6464
{
65-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
65+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
6666
{
6767
await Task.Delay(ModuleDelay, cancellationToken);
68-
return null;
68+
return true;
6969
}
7070
}
7171

7272
[ModularPipelines.Attributes.DependsOn<Module1>(IgnoreIfNotRegistered = true)]
7373
private class Module3 : BaseModule
7474
{
75-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
75+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
7676
{
7777
await Task.Delay(ModuleDelay, cancellationToken);
78-
return null;
78+
return true;
7979
}
8080
}
8181

8282
[ModularPipelines.Attributes.DependsOnAllModulesInheritingFrom<BaseModule>]
83-
private class Module4 : Module<IDictionary<string, object>?>
83+
private class Module4 : Module<bool>
8484
{
85-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
85+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
8686
{
8787
await Task.Yield();
88-
return null;
88+
return true;
8989
}
9090
}
9191

test/ModularPipelines.UnitTests/DependsOnTests.cs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,76 +9,76 @@ namespace ModularPipelines.UnitTests;
99

1010
public class DependsOnTests : TestBase
1111
{
12-
private class Module1 : Module<IDictionary<string, object>?>
12+
private class Module1 : Module<bool>
1313
{
14-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
14+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
1515
{
1616
await Task.Yield();
17-
return null;
17+
return true;
1818
}
1919
}
2020

2121
[ModularPipelines.Attributes.DependsOn<Module1>]
22-
private class Module2 : Module<IDictionary<string, object>?>
22+
private class Module2 : Module<bool>
2323
{
24-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
24+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
2525
{
2626
await Task.Yield();
27-
return null;
27+
return true;
2828
}
2929
}
3030

3131
[ModularPipelines.Attributes.DependsOn<Module1>(IgnoreIfNotRegistered = true)]
32-
private class Module3 : Module<IDictionary<string, object>?>
32+
private class Module3 : Module<bool>
3333
{
34-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
34+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
3535
{
3636
await Task.Yield();
37-
return null;
37+
return true;
3838
}
3939
}
4040

4141
[ModularPipelines.Attributes.DependsOn<Module1>(IgnoreIfNotRegistered = true)]
42-
private class Module3WithGetIfRegistered : Module<IDictionary<string, object>?>
42+
private class Module3WithGetIfRegistered : Module<bool>
4343
{
44-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
44+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
4545
{
46-
_ = context.GetModuleIfRegistered<Module1, IDictionary<string, object>?>();
46+
_ = context.GetModuleIfRegistered<Module1, bool>();
4747
await Task.Yield();
48-
return null;
48+
return true;
4949
}
5050
}
5151

5252
[ModularPipelines.Attributes.DependsOn<Module1>(IgnoreIfNotRegistered = true)]
53-
private class Module3WithGet : Module<IDictionary<string, object>?>
53+
private class Module3WithGet : Module<bool>
5454
{
55-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
55+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
5656
{
57-
_ = context.GetModule<Module1, IDictionary<string, object>?>();
57+
_ = context.GetModule<Module1, bool>();
5858
await Task.Yield();
59-
return null;
59+
return true;
6060
}
6161
}
6262

6363
[ModularPipelines.Attributes.DependsOn<DependsOnSelfModule>]
64-
private class DependsOnSelfModule : Module<IDictionary<string, object>?>
64+
private class DependsOnSelfModule : Module<bool>
6565
{
66-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
66+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
6767
{
68-
_ = context.GetModule<Module1, IDictionary<string, object>?>();
68+
_ = context.GetModule<Module1, bool>();
6969
await Task.Yield();
70-
return null;
70+
return true;
7171
}
7272
}
7373

7474
[ModularPipelines.Attributes.DependsOn(typeof(ModuleFailedException))]
75-
private class DependsOnNonModule : Module<IDictionary<string, object>?>
75+
private class DependsOnNonModule : Module<bool>
7676
{
77-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
77+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
7878
{
79-
_ = context.GetModule<Module1, IDictionary<string, object>?>();
79+
_ = context.GetModule<Module1, bool>();
8080
await Task.Yield();
81-
return null;
81+
return true;
8282
}
8383
}
8484

test/ModularPipelines.UnitTests/DirectCollisionTests.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,23 @@ await Assert.That(() => TestPipelineHostBuilder.Create()
2020
}
2121

2222
[ModularPipelines.Attributes.DependsOn<DependencyConflictModule2>]
23-
private class DependencyConflictModule1 : Module<IDictionary<string, object>?>
23+
private class DependencyConflictModule1 : Module<bool>
2424
{
25-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
25+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
2626
{
27-
_ = context.GetModule<DependencyConflictModule2, IDictionary<string, object>?>();
27+
_ = context.GetModule<DependencyConflictModule2, bool>();
2828
await Task.Yield();
29-
return null;
29+
return true;
3030
}
3131
}
3232

3333
[ModularPipelines.Attributes.DependsOn<DependencyConflictModule1>]
34-
private class DependencyConflictModule2 : Module<IDictionary<string, object>?>
34+
private class DependencyConflictModule2 : Module<bool>
3535
{
36-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
36+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
3737
{
3838
await Task.CompletedTask;
39-
return null;
39+
return true;
4040
}
4141
}
4242
}

test/ModularPipelines.UnitTests/DisposableModuleTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ public async Task SuccessfullyDisposed()
1515
await Assert.That(pipelineSummary.Modules.OfType<DisposableModule>().Single().IsDisposed).IsTrue();
1616
}
1717

18-
public class DisposableModule : Module<IDictionary<string, object>?>, IDisposable
18+
public class DisposableModule : Module<bool>, IDisposable
1919
{
2020
public bool IsDisposed { get; private set; }
2121

2222
/// <inheritdoc/>
23-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
23+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
2424
{
2525
// Reduced delay from 100ms to 1ms for faster test execution
2626
await Task.Delay(1, cancellationToken);
27-
return null;
27+
return true;
2828
}
2929

3030
/// <inheritdoc/>

test/ModularPipelines.UnitTests/EngineCancellationTokenTests.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,45 +14,45 @@ public class EngineCancellationTokenTests : TestBase
1414
{
1515
private static readonly TimeSpan WaitForCancellationDelay = TimeSpan.FromMilliseconds(100);
1616

17-
private class BadModule : Module<IDictionary<string, object>?>
17+
private class BadModule : Module<bool>
1818
{
19-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
19+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
2020
{
2121
await Task.Yield();
2222
throw new Exception();
2323
}
2424
}
2525

2626
[ModularPipelines.Attributes.DependsOn<BadModule>]
27-
private class Module1 : Module<IDictionary<string, object>?>
27+
private class Module1 : Module<bool>
2828
{
29-
public override Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
29+
public override Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
3030
{
31-
return Task.FromResult<IDictionary<string, object>?>(null);
31+
return Task.FromResult(true);
3232
}
3333
}
3434

35-
private class LongRunningModule : Module<IDictionary<string, object>?>
35+
private class LongRunningModule : Module<bool>
3636
{
3737
private readonly TaskCompletionSource<bool> _taskCompletionSource = new();
3838

39-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
39+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
4040
{
4141
await _taskCompletionSource.Task.WaitAsync(cancellationToken);
42-
return null;
42+
return true;
4343
}
4444
}
4545

46-
private class LongRunningModuleWithoutCancellation : Module<IDictionary<string, object>?>, ITimeoutable
46+
private class LongRunningModuleWithoutCancellation : Module<bool>, ITimeoutable
4747
{
4848
private readonly TaskCompletionSource<bool> _taskCompletionSource = new();
4949

5050
public TimeSpan Timeout => TimeSpan.FromSeconds(1);
5151

52-
public override async Task<IDictionary<string, object>?> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
52+
public override async Task<bool> ExecuteAsync(IModuleContext context, CancellationToken cancellationToken)
5353
{
5454
await _taskCompletionSource.Task;
55-
return null;
55+
return true;
5656
}
5757
}
5858

0 commit comments

Comments
 (0)