diff --git a/docs/input/cli/commandApp.md b/docs/input/cli/commandApp.md
index c003f60..f940059 100644
--- a/docs/input/cli/commandApp.md
+++ b/docs/input/cli/commandApp.md
@@ -74,6 +74,9 @@ return app.Run(args);
`TypeRegistrar` is a custom class that must be created by the user. This [example using `Microsoft.Extensions.DependencyInjection` as the container](https://github.com/spectreconsole/spectre.console/tree/main/examples/Cli/Injection) provides an example `TypeRegistrar` and `TypeResolver` that can be added to your application with small adjustments for your DI container.
+Hint: If you do write your own implementation of `TypeRegistrar` and `TypeResolver` and you have some form of unit tests in place for your project,
+there is a utility `TypeRegistrarBaseTests` available that can be used to ensure your implementations adhere to the required implementation. Simply call `TypeRegistrarBaseTests.RunAllTests()` and expect no `TypeRegistrarBaseTests.TestFailedException` to be thrown.
+
## Interception
`CommandApp` also provides a `SetInterceptor` configuration. An interceptor is run before all commands are executed. This is typically used for configuring logging or other infrastructure concerns.
diff --git a/src/Spectre.Console.Testing/Cli/TypeRegistrarBaseTests.cs b/src/Spectre.Console.Testing/Cli/TypeRegistrarBaseTests.cs
new file mode 100644
index 0000000..8980a98
--- /dev/null
+++ b/src/Spectre.Console.Testing/Cli/TypeRegistrarBaseTests.cs
@@ -0,0 +1,191 @@
+using System;
+using Spectre.Console.Cli;
+
+namespace Spectre.Console.Testing
+{
+ ///
+ /// This is a utility class for implementors of
+ /// and corresponding .
+ ///
+ public sealed class TypeRegistrarBaseTests
+ {
+ private readonly Func _registrarFactory;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The factory to create a new, clean to be used for each test.
+ public TypeRegistrarBaseTests(Func registrarFactory)
+ {
+ _registrarFactory = registrarFactory;
+ }
+
+ ///
+ /// Runs all tests.
+ ///
+ /// This exception is raised, if a test fails.
+ public void RunAllTests()
+ {
+ var testCases = new Action[]
+ {
+ RegistrationsCanBeResolved,
+ InstanceRegistrationsCanBeResolved,
+ LazyRegistrationsCanBeResolved,
+ ResolvingNotRegisteredServiceReturnsNull,
+ ResolvingNullTypeReturnsNull,
+ };
+
+ foreach (var test in testCases)
+ {
+ test(_registrarFactory());
+ }
+ }
+
+ private static void ResolvingNullTypeReturnsNull(ITypeRegistrar registrar)
+ {
+ // Given no registration
+ var resolver = registrar.Build();
+
+ try
+ {
+ // When
+ var actual = resolver.Resolve(null);
+
+ // Then
+ if (actual != null)
+ {
+ throw new TestFailedException(
+ $"Expected the resolver to resolve null, since null was requested as the service type. Actually resolved {actual.GetType().Name}.");
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new TestFailedException(
+ $"Expected the resolver not to throw, but caught {ex.GetType().Name}.", ex);
+ }
+ }
+
+ private static void ResolvingNotRegisteredServiceReturnsNull(ITypeRegistrar registrar)
+ {
+ // Given no registration
+ var resolver = registrar.Build();
+
+ try
+ {
+ // When
+ var actual = resolver.Resolve(typeof(IMockService));
+
+ // Then
+ if (actual != null)
+ {
+ throw new TestFailedException(
+ $"Expected the resolver to resolve null, since no service was registered. Actually resolved {actual.GetType().Name}.");
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new TestFailedException(
+ $"Expected the resolver not to throw, but caught {ex.GetType().Name}.", ex);
+ }
+ }
+
+ private static void RegistrationsCanBeResolved(ITypeRegistrar registrar)
+ {
+ // Given
+ registrar.Register(typeof(IMockService), typeof(MockService));
+ var resolver = registrar.Build();
+
+ // When
+ var actual = resolver.Resolve(typeof(IMockService));
+
+ // Then
+ if (actual == null)
+ {
+ throw new TestFailedException(
+ $"Expected the resolver to resolve an instance of {nameof(MockService)}. Actually resolved null.");
+ }
+
+ if (actual is not MockService)
+ {
+ throw new TestFailedException(
+ $"Expected the resolver to resolve an instance of {nameof(MockService)}. Actually resolved {actual.GetType().Name}.");
+ }
+ }
+
+ private static void InstanceRegistrationsCanBeResolved(ITypeRegistrar registrar)
+ {
+ // Given
+ var instance = new MockService();
+ registrar.RegisterInstance(typeof(IMockService), instance);
+ var resolver = registrar.Build();
+
+ // When
+ var actual = resolver.Resolve(typeof(IMockService));
+
+ // Then
+ if (!ReferenceEquals(actual, instance))
+ {
+ throw new TestFailedException(
+ "Expected the resolver to resolve exactly the registered instance.");
+ }
+ }
+
+ private static void LazyRegistrationsCanBeResolved(ITypeRegistrar registrar)
+ {
+ // Given
+ var instance = new MockService();
+ var factoryCalled = false;
+ registrar.RegisterLazy(typeof(IMockService), () =>
+ {
+ factoryCalled = true;
+ return instance;
+ });
+ var resolver = registrar.Build();
+
+ // When
+ var actual = resolver.Resolve(typeof(IMockService));
+
+ // Then
+ if (!factoryCalled)
+ {
+ throw new TestFailedException(
+ "Expected the factory to be called, to resolve the lazy registration.");
+ }
+
+ if (!ReferenceEquals(actual, instance))
+ {
+ throw new TestFailedException(
+ "Expected the resolver to return exactly the result of the lazy-registered factory.");
+ }
+ }
+
+ ///
+ /// internal use only.
+ ///
+ private interface IMockService
+ {
+ }
+
+ private class MockService : IMockService
+ {
+ }
+
+ ///
+ /// Exception, to be raised when a test fails.
+ ///
+ public sealed class TestFailedException : Exception
+ {
+ ///
+ public TestFailedException(string message)
+ : base(message)
+ {
+ }
+
+ ///
+ public TestFailedException(string message, Exception inner)
+ : base(message, inner)
+ {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Spectre.Console/Spectre.Console.csproj b/src/Spectre.Console/Spectre.Console.csproj
index 41f0a16..2c90a3f 100644
--- a/src/Spectre.Console/Spectre.Console.csproj
+++ b/src/Spectre.Console/Spectre.Console.csproj
@@ -17,6 +17,7 @@
+
diff --git a/test/Spectre.Console.Tests/Spectre.Console.Tests.csproj b/test/Spectre.Console.Tests/Spectre.Console.Tests.csproj
index dd5bb05..d3e5802 100644
--- a/test/Spectre.Console.Tests/Spectre.Console.Tests.csproj
+++ b/test/Spectre.Console.Tests/Spectre.Console.Tests.csproj
@@ -6,10 +6,6 @@
9.0
-
-
-
-
@@ -24,7 +20,6 @@
-
diff --git a/test/Spectre.Console.Tests/Unit/Cli/DefaultTypeRegistrarTests.cs b/test/Spectre.Console.Tests/Unit/Cli/DefaultTypeRegistrarTests.cs
new file mode 100644
index 0000000..9356cfe
--- /dev/null
+++ b/test/Spectre.Console.Tests/Unit/Cli/DefaultTypeRegistrarTests.cs
@@ -0,0 +1,16 @@
+using Spectre.Console.Cli;
+using Spectre.Console.Testing;
+using Xunit;
+
+namespace Spectre.Console.Tests.Unit.Cli
+{
+ public sealed class DefaultTypeRegistrarTests
+ {
+ [Fact]
+ public void Should_Pass_Base_Registrar_Tests()
+ {
+ var harness = new TypeRegistrarBaseTests(() => new DefaultTypeRegistrar());
+ harness.RunAllTests();
+ }
+ }
+}
\ No newline at end of file