Skip to content

Commit 8c499f5

Browse files
committed
Add XML documentation comments to public APIs #314
Added XML doc comments to public classes, methods, and properties throughout the codebase to improve API discoverability and enable NuGet documentation generation. Updated the project file to generate XML documentation output and suppress missing comment warnings. No functional changes were made.
1 parent 9243f82 commit 8c499f5

12 files changed

+163
-13
lines changed

src/Abstracts/TestBed.cs

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,59 @@
11
namespace Xunit.Microsoft.DependencyInjection.Abstracts;
22

3+
/// <summary>
4+
/// Base class for test classes which use a fixture of type <typeparamref name="TFixture"/>.
5+
/// Provides synchronous and asynchronous disposal semantics and a hook (<see cref="Clear"/>)
6+
/// that derived classes can override to release managed resources created during tests.
7+
/// </summary>
8+
/// <typeparam name="TFixture">The fixture type shared across all tests in the class.</typeparam>
39
public class TestBed<TFixture>(ITestOutputHelper testOutputHelper, TFixture fixture) : IDisposable, IClassFixture<TFixture>, IAsyncDisposable
410
where TFixture : class
511
{
12+
/// <summary>
13+
/// The <see cref="ITestOutputHelper"/> used to write diagnostic output during test execution.
14+
/// </summary>
615
protected readonly ITestOutputHelper _testOutputHelper = testOutputHelper;
16+
17+
/// <summary>
18+
/// The fixture instance supplied by xUnit for this test class.
19+
/// </summary>
720
protected readonly TFixture _fixture = fixture;
21+
822
private bool _disposedValue;
923
private bool _disposedAsync;
1024

25+
/// <summary>
26+
/// Releases managed resources. Override to add custom cleanup logic. Unmanaged resources
27+
/// should be released only if added by derived classes.
28+
/// </summary>
29+
/// <param name="disposing">True when called from <see cref="Dispose()"/>; false when from a finalizer.</param>
1130
protected virtual void Dispose(bool disposing)
1231
{
1332
if (!_disposedValue)
1433
{
1534
if (disposing)
1635
{
17-
// TODO: dispose managed state (managed objects)
36+
// Dispose managed state
1837
Clear();
1938
}
20-
21-
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
22-
// TODO: set large fields to null
2339
_disposedValue = true;
2440
}
2541
}
2642

27-
// // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
28-
// ~AbstractTest()
29-
// {
30-
// // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
31-
// Dispose(disposing: false);
32-
// }
43+
// Finalizer intentionally omitted. Add only if unmanaged resources are introduced.
3344

45+
/// <summary>
46+
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
47+
/// </summary>
3448
public void Dispose()
3549
{
36-
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
3750
Dispose(disposing: true);
3851
GC.SuppressFinalize(this);
3952
}
4053

54+
/// <summary>
55+
/// Asynchronously disposes resources. Calls <see cref="DisposeAsyncCore"/> once.
56+
/// </summary>
4157
public async ValueTask DisposeAsync()
4258
{
4359
if (!_disposedAsync)
@@ -48,6 +64,14 @@ public async ValueTask DisposeAsync()
4864
}
4965
}
5066

67+
/// <summary>
68+
/// Override to clear managed resources created by a derived test class.
69+
/// </summary>
5170
protected virtual void Clear() { }
71+
72+
/// <summary>
73+
/// Override to implement asynchronous disposal of resources.
74+
/// Default implementation is a completed <see cref="ValueTask"/>.
75+
/// </summary>
5276
protected virtual ValueTask DisposeAsyncCore() => new();
5377
}

src/Abstracts/TestBedFactoryFixture.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,18 @@ public object CreateTestInstance(Type testType, ITestOutputHelper testOutputHelp
3636

3737

3838

39+
/// <summary>
40+
/// Creates an instance of <typeparamref name="T"/> using the best matching constructor.
41+
/// </summary>
3942
private T CreateInstance<T>(IServiceProvider serviceProvider, ITestOutputHelper testOutputHelper, params object[] additionalParameters)
4043
where T : class => (T)CreateInstance(typeof(T), serviceProvider, testOutputHelper, additionalParameters);
4144

45+
/// <summary>
46+
/// Core implementation for creating the test instance by iterating available constructors
47+
/// (public &amp; non-public) and resolving parameters from provided instances, test output helper,
48+
/// the fixture itself or the service provider (including keyed services when annotated).
49+
/// </summary>
50+
/// <exception cref="InvalidOperationException">Thrown when no suitable constructor can be satisfied.</exception>
4251
private object CreateInstance(Type testType, IServiceProvider serviceProvider, ITestOutputHelper testOutputHelper, params object[] additionalParameters)
4352
{
4453
// Find the best constructor (including internal constructors)

src/Abstracts/TestBedFixture.cs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
namespace Xunit.Microsoft.DependencyInjection.Abstracts;
44

5+
/// <summary>
6+
/// Base fixture abstraction that configures dependency injection, configuration sources
7+
/// (JSON, user secrets, environment variables) and logging for test classes.
8+
/// Derived fixtures register services via <see cref="AddServices"/> and configuration files
9+
/// via <see cref="GetTestAppSettings"/>.
10+
/// </summary>
511
public abstract class TestBedFixture : IDisposable, IAsyncDisposable
612
{
713
private readonly ServiceCollection _services;
@@ -10,6 +16,9 @@ public abstract class TestBedFixture : IDisposable, IAsyncDisposable
1016
private bool _disposedAsync;
1117
private bool _servicesAdded;
1218

19+
/// <summary>
20+
/// Initializes the fixture, creating a service collection and configuration builder.
21+
/// </summary>
1322
protected TestBedFixture()
1423
{
1524
_services = new ServiceCollection();
@@ -19,9 +28,21 @@ protected TestBedFixture()
1928
_servicesAdded = false;
2029
}
2130

31+
/// <summary>
32+
/// The combined configuration root composed of JSON files, user secrets (optional) and environment variables.
33+
/// </summary>
2234
public IConfigurationRoot? Configuration { get; private set; }
35+
36+
/// <summary>
37+
/// The configuration builder used to assemble the <see cref="Configuration"/>.
38+
/// </summary>
2339
public IConfigurationBuilder ConfigurationBuilder { get; private set; }
2440

41+
/// <summary>
42+
/// Builds (lazily) and returns the root <see cref="ServiceProvider"/> including logging provider and options.
43+
/// Subsequent calls return a cached provider.
44+
/// </summary>
45+
/// <param name="testOutputHelper">The test output helper used for logging.</param>
2546
public ServiceProvider GetServiceProvider(ITestOutputHelper testOutputHelper)
2647
{
2748
if (_serviceProvider is not null)
@@ -38,22 +59,37 @@ public ServiceProvider GetServiceProvider(ITestOutputHelper testOutputHelper)
3859
return _serviceProvider = _services.BuildServiceProvider();
3960
}
4061

62+
/// <summary>
63+
/// Resolves a scoped service of type <typeparamref name="T"/> using a new scope.
64+
/// </summary>
4165
public T? GetScopedService<T>(ITestOutputHelper testOutputHelper)
4266
{
4367
var serviceProvider = GetServiceProvider(testOutputHelper);
4468
using var scope = serviceProvider.CreateScope();
4569
return scope.ServiceProvider.GetService<T>();
4670
}
4771

72+
/// <summary>
73+
/// Creates and returns a new asynchronous service scope.
74+
/// Caller is responsible for disposing the returned <see cref="AsyncServiceScope"/>.
75+
/// </summary>
4876
public AsyncServiceScope GetAsyncScope(ITestOutputHelper testOutputHelper)
4977
{
5078
var serviceProvider = GetServiceProvider(testOutputHelper);
5179
return serviceProvider.CreateAsyncScope();
5280
}
5381

82+
/// <summary>
83+
/// Resolves a service of type <typeparamref name="T"/> from the root provider.
84+
/// </summary>
5485
public T? GetService<T>(ITestOutputHelper testOutputHelper)
5586
=> GetServiceProvider(testOutputHelper).GetService<T>();
5687

88+
/// <summary>
89+
/// Resolves a keyed service of type <typeparamref name="T"/>.
90+
/// </summary>
91+
/// <param name="key">The key identifying the registration.</param>
92+
/// <param name="testOutputHelper">The test output helper used for logging and provider access.</param>
5793
public T? GetKeyedService<T>([DisallowNull] string key, ITestOutputHelper testOutputHelper)
5894
=> GetServiceProvider(testOutputHelper).GetKeyedService<T>(key);
5995

@@ -64,13 +100,15 @@ public AsyncServiceScope GetAsyncScope(ITestOutputHelper testOutputHelper)
64100
// Dispose(disposing: false);
65101
// }
66102

103+
/// <inheritdoc />
67104
public void Dispose()
68105
{
69106
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
70107
Dispose(disposing: true);
71108
GC.SuppressFinalize(this);
72109
}
73110

111+
/// <inheritdoc />
74112
public async ValueTask DisposeAsync()
75113
{
76114
if (!_disposedAsync)
@@ -82,13 +120,31 @@ public async ValueTask DisposeAsync()
82120
GC.SuppressFinalize(this);
83121
}
84122

123+
/// <summary>
124+
/// Adds services to the service collection. Called once before building the provider.
125+
/// </summary>
85126
protected abstract void AddServices(IServiceCollection services, IConfiguration? configuration);
127+
128+
/// <summary>
129+
/// Returns the test application settings descriptors (JSON files) to include.
130+
/// </summary>
86131
protected abstract IEnumerable<TestAppSettings> GetTestAppSettings();
132+
133+
/// <summary>
134+
/// Override to asynchronously clean up resources created by the fixture.
135+
/// </summary>
87136
protected abstract ValueTask DisposeAsyncCore();
88137

138+
/// <summary>
139+
/// Allows derived fixtures to customize logging by adding or decorating providers.
140+
/// </summary>
89141
protected virtual ILoggingBuilder AddLoggingProvider(ILoggingBuilder loggingBuilder, ILoggerProvider loggerProvider)
90142
=> loggingBuilder.AddProvider(loggerProvider);
91143

144+
/// <summary>
145+
/// Override to add user secrets to the provided configuration builder when needed.
146+
/// Default implementation does nothing.
147+
/// </summary>
92148
protected virtual void AddUserSecrets(IConfigurationBuilder configurationBuilder) { }
93149

94150
private IConfigurationRoot? GetConfigurationRoot()
@@ -110,6 +166,9 @@ private IConfigurationRoot GetConfigurationRoot(IEnumerable<TestAppSettings> con
110166
return ConfigurationBuilder.Build();
111167
}
112168

169+
/// <summary>
170+
/// Disposes managed resources created by the fixture including the root service provider.
171+
/// </summary>
113172
protected virtual void Dispose(bool disposing)
114173
{
115174
if (!_disposedValue)
@@ -124,8 +183,6 @@ protected virtual void Dispose(bool disposing)
124183
_services.Clear();
125184
}
126185

127-
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
128-
// TODO: set large fields to null
129186
_disposedValue = true;
130187
}
131188
}

src/Abstracts/TestBedWithDI.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,19 @@ private void InjectProperties(Type derivedType)
8383
/// </summary>
8484
/// <typeparam name="T">The service type</typeparam>
8585
/// <returns>The resolved service instance</returns>
86+
/// <summary>
87+
/// Convenience helper to resolve a service of type <typeparamref name="T"/>.
88+
/// </summary>
8689
protected T? GetService<T>() => _fixture.GetService<T>(_testOutputHelper);
8790

8891
/// <summary>
8992
/// Resolves a scoped service of type T from the fixture's service provider
9093
/// </summary>
9194
/// <typeparam name="T">The service type</typeparam>
9295
/// <returns>The resolved service instance</returns>
96+
/// <summary>
97+
/// Convenience helper to resolve a scoped service of type <typeparamref name="T"/>.
98+
/// </summary>
9399
protected T? GetScopedService<T>() => _fixture.GetScopedService<T>(_testOutputHelper);
94100

95101
/// <summary>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
namespace Xunit.Microsoft.DependencyInjection.Attributes;
22

3+
/// <summary>
4+
/// Specifies execution ordering for test methods when used with <see cref="TestsOrder.TestPriorityOrderer"/>.
5+
/// Lower priority values execute first; methods with the same priority are ordered alphabetically.
6+
/// </summary>
37
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
48
public class TestOrderAttribute(int priority) : Attribute
59
{
10+
/// <summary>
11+
/// Gets the priority assigned to the test method.
12+
/// </summary>
613
public int Priority { get; } = priority;
714
}

src/Logging/NilLoggerProvider.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
namespace Xunit.Microsoft.DependencyInjection.Logging;
22

3+
/// <summary>
4+
/// Logger provider that discards all log messages (Null Object pattern).
5+
/// Useful for suppressing output when no <see cref="ITestOutputHelper"/> is available.
6+
/// </summary>
37
public sealed class NilLoggerProvider : ILoggerProvider
48
{
9+
/// <inheritdoc />
510
public ILogger CreateLogger(string categoryName)
611
=> new NilLogger();
712

13+
/// <inheritdoc />
814
public void Dispose()
915
{
1016
}

src/Logging/NoOpDisposable.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
namespace Xunit.Microsoft.DependencyInjection.Logging;
22

3+
/// <summary>
4+
/// Lightweight disposable that performs no action. Used to satisfy API contracts requiring a disposable scope.
5+
/// </summary>
36
internal class NoOpDisposable : IDisposable
47
{
8+
/// <inheritdoc />
59
public void Dispose() { }
610
}

src/Logging/OutputLogger.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
namespace Xunit.Microsoft.DependencyInjection.Logging;
22

3+
/// <summary>
4+
/// An <see cref="ILogger"/> implementation that writes log messages to the xUnit <see cref="ITestOutputHelper"/>.
5+
/// </summary>
36
public class OutputLogger(string categoryName, ITestOutputHelper testOutputHelper) : ILogger
47
{
58
private readonly ITestOutputHelper _testOutputHelper = testOutputHelper;
69
private readonly string _categoryName = categoryName;
710

11+
/// <summary>
12+
/// Creates a logger with the default category name "Tests".
13+
/// </summary>
814
public OutputLogger(ITestOutputHelper testOutputHelper)
915
: this("Tests", testOutputHelper)
1016
{
@@ -16,6 +22,7 @@ public OutputLogger(ITestOutputHelper testOutputHelper)
1622
public bool IsEnabled(LogLevel logLevel)
1723
=> true;
1824

25+
/// <inheritdoc />
1926
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception, string> formatter)
2027
{
2128
try

src/Logging/OutputLoggerProvider.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
namespace Xunit.Microsoft.DependencyInjection.Logging;
22

3+
/// <summary>
4+
/// Logger provider that creates <see cref="OutputLogger"/> instances writing to a shared
5+
/// <see cref="ITestOutputHelper"/>.
6+
/// </summary>
37
public class OutputLoggerProvider(ITestOutputHelper testOutputHelper) : ILoggerProvider
48
{
59
private readonly ITestOutputHelper _testOutputHelper = testOutputHelper;

src/TestAppSettings.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
namespace Xunit.Microsoft.DependencyInjection;
22

3+
/// <summary>
4+
/// Represents a test configuration file to be loaded into the fixture configuration root.
5+
/// </summary>
36
public class TestAppSettings
47
{
8+
/// <summary>
9+
/// The JSON file name (relative or absolute) to load.
10+
/// </summary>
511
public string? Filename { get; set; }
12+
13+
/// <summary>
14+
/// Indicates whether the file is optional. When true missing files do not cause an exception.
15+
/// </summary>
616
public bool IsOptional { get; set; } = false;
717
}

0 commit comments

Comments
 (0)