diff --git a/src/Aspire.Hosting.Oracle/OracleDatabaseBuilderExtensions.cs b/src/Aspire.Hosting.Oracle/OracleDatabaseBuilderExtensions.cs
index 8b431319488..230f7163ab8 100644
--- a/src/Aspire.Hosting.Oracle/OracleDatabaseBuilderExtensions.cs
+++ b/src/Aspire.Hosting.Oracle/OracleDatabaseBuilderExtensions.cs
@@ -27,6 +27,9 @@ public static class OracleDatabaseBuilderExtensions
/// A reference to the .
public static IResourceBuilder AddOracle(this IDistributedApplicationBuilder builder, [ResourceName] string name, IResourceBuilder? password = null, int? port = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(name);
+
var passwordParameter = password?.Resource ?? ParameterResourceBuilderExtensions.CreateDefaultPasswordParameter(builder, $"{name}-password");
var oracleDatabaseServer = new OracleDatabaseServerResource(name, passwordParameter);
@@ -67,6 +70,9 @@ public static IResourceBuilder AddOracle(this IDis
/// A reference to the .
public static IResourceBuilder AddDatabase(this IResourceBuilder builder, [ResourceName] string name, string? databaseName = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(name);
+
// Use the resource name as the database name if it's not provided
databaseName ??= name;
@@ -82,7 +88,11 @@ public static IResourceBuilder AddDatabase(this IResourc
/// The name of the volume. Defaults to an auto-generated name based on the application and resource names.
/// The .
public static IResourceBuilder WithDataVolume(this IResourceBuilder builder, string? name = null)
- => builder.WithVolume(name ?? VolumeNameGenerator.Generate(builder, "data"), "/opt/oracle/oradata", false);
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ return builder.WithVolume(name ?? VolumeNameGenerator.Generate(builder, "data"), "/opt/oracle/oradata", false);
+ }
///
/// Adds a bind mount for the data folder to a Oracle Database server container resource.
@@ -91,7 +101,12 @@ public static IResourceBuilder WithDataVolume(this
/// The source directory on the host to mount into the container.
/// The .
public static IResourceBuilder WithDataBindMount(this IResourceBuilder builder, string source)
- => builder.WithBindMount(source, "/opt/oracle/oradata", false);
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(source);
+
+ return builder.WithBindMount(source, "/opt/oracle/oradata", false);
+ }
///
/// Adds a bind mount for the init folder to a Oracle Database server container resource.
@@ -100,7 +115,12 @@ public static IResourceBuilder WithDataBindMount(t
/// The source directory on the host to mount into the container.
/// The .
public static IResourceBuilder WithInitBindMount(this IResourceBuilder builder, string source)
- => builder.WithBindMount(source, "/opt/oracle/scripts/startup", false);
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(source);
+
+ return builder.WithBindMount(source, "/opt/oracle/scripts/startup", false);
+ }
///
/// Adds a bind mount for the database setup folder to a Oracle Database server container resource.
@@ -109,5 +129,10 @@ public static IResourceBuilder WithInitBindMount(t
/// The source directory on the host to mount into the container.
/// The .
public static IResourceBuilder WithDbSetupBindMount(this IResourceBuilder builder, string source)
- => builder.WithBindMount(source, "/opt/oracle/scripts/setup", false);
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(source);
+
+ return builder.WithBindMount(source, "/opt/oracle/scripts/setup", false);
+ }
}
diff --git a/src/Aspire.Hosting.Oracle/OracleDatabaseResource.cs b/src/Aspire.Hosting.Oracle/OracleDatabaseResource.cs
index 82a8ab9de0f..11087ec6974 100644
--- a/src/Aspire.Hosting.Oracle/OracleDatabaseResource.cs
+++ b/src/Aspire.Hosting.Oracle/OracleDatabaseResource.cs
@@ -1,6 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
namespace Aspire.Hosting.ApplicationModel;
///
@@ -9,12 +12,12 @@ namespace Aspire.Hosting.ApplicationModel;
/// The name of the resource.
/// The database name.
/// The Oracle Database parent resource associated with this database.
-public class OracleDatabaseResource(string name, string databaseName, OracleDatabaseServerResource parent) : Resource(name), IResourceWithParent, IResourceWithConnectionString
+public class OracleDatabaseResource(string name, string databaseName, OracleDatabaseServerResource parent) : Resource(ThrowIfNullOrEmpty(name)), IResourceWithParent, IResourceWithConnectionString
{
///
/// Gets the parent Oracle container resource.
///
- public OracleDatabaseServerResource Parent { get; } = parent;
+ public OracleDatabaseServerResource Parent { get; } = ThrowIfNullOrEmpty(parent);
///
/// Gets the connection string expression for the Oracle Database.
@@ -25,5 +28,19 @@ public class OracleDatabaseResource(string name, string databaseName, OracleData
///
/// Gets the database name.
///
- public string DatabaseName { get; } = databaseName;
+ public string DatabaseName { get; } = ThrowIfNullOrEmpty(databaseName);
+
+ private static T ThrowIfNullOrEmpty([NotNull] T? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
+ {
+ ArgumentNullException.ThrowIfNull(argument, paramName);
+
+ if (argument is not string str)
+ {
+ return argument;
+ }
+
+ ArgumentException.ThrowIfNullOrEmpty(str, paramName);
+ return argument;
+
+ }
}
diff --git a/src/Aspire.Hosting.Oracle/OracleDatabaseServerResource.cs b/src/Aspire.Hosting.Oracle/OracleDatabaseServerResource.cs
index e066fea7370..7fccbc160b5 100644
--- a/src/Aspire.Hosting.Oracle/OracleDatabaseServerResource.cs
+++ b/src/Aspire.Hosting.Oracle/OracleDatabaseServerResource.cs
@@ -1,6 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
namespace Aspire.Hosting.ApplicationModel;
///
@@ -15,9 +18,9 @@ public class OracleDatabaseServerResource : ContainerResource, IResourceWithConn
///
/// The name of the resource.
/// A parameter that contains the Oracle Database server password.
- public OracleDatabaseServerResource(string name, ParameterResource password) : base(name)
+ public OracleDatabaseServerResource(string name, ParameterResource password) : base(ThrowIfNullOrEmpty(name))
{
- ArgumentNullException.ThrowIfNull(password);
+ ThrowIfNullOrEmpty(password);
PrimaryEndpoint = new(this, PrimaryEndpointName);
PasswordParameter = password;
@@ -51,4 +54,18 @@ internal void AddDatabase(string name, string databaseName)
{
_databases.TryAdd(name, databaseName);
}
+
+ private static T ThrowIfNullOrEmpty([NotNull] T? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
+ {
+ ArgumentNullException.ThrowIfNull(argument, paramName);
+
+ if (argument is not string str)
+ {
+ return argument;
+ }
+
+ ArgumentException.ThrowIfNullOrEmpty(str, paramName);
+ return argument;
+
+ }
}
diff --git a/src/Components/Aspire.Pomelo.EntityFrameworkCore.MySql/AspireEFMySqlExtensions.cs b/src/Components/Aspire.Pomelo.EntityFrameworkCore.MySql/AspireEFMySqlExtensions.cs
index 793405a8a31..224e549f0dd 100644
--- a/src/Components/Aspire.Pomelo.EntityFrameworkCore.MySql/AspireEFMySqlExtensions.cs
+++ b/src/Components/Aspire.Pomelo.EntityFrameworkCore.MySql/AspireEFMySqlExtensions.cs
@@ -53,6 +53,7 @@ public static partial class AspireEFMySqlExtensions
Action? configureDbContextOptions = null) where TContext : DbContext
{
ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
builder.EnsureDbContextNotRegistered();
diff --git a/src/Components/Aspire.Qdrant.Client/AspireQdrantExtensions.cs b/src/Components/Aspire.Qdrant.Client/AspireQdrantExtensions.cs
index 358fd6a1218..4ed008f65db 100644
--- a/src/Components/Aspire.Qdrant.Client/AspireQdrantExtensions.cs
+++ b/src/Components/Aspire.Qdrant.Client/AspireQdrantExtensions.cs
@@ -32,6 +32,8 @@ public static void AddQdrantClient(
string connectionName,
Action? configureSettings = null)
{
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
AddQdrant(builder, configureSettings, connectionName, serviceKey: null);
}
@@ -49,6 +51,8 @@ public static void AddKeyedQdrantClient(
string name,
Action? configureSettings = null)
{
+ ArgumentException.ThrowIfNullOrEmpty(name);
+
AddQdrant(builder, configureSettings, connectionName: name, serviceKey: name);
}
diff --git a/src/Components/Aspire.RabbitMQ.Client/AspireRabbitMQExtensions.cs b/src/Components/Aspire.RabbitMQ.Client/AspireRabbitMQExtensions.cs
index b13fcfe6bc0..8850216b72a 100644
--- a/src/Components/Aspire.RabbitMQ.Client/AspireRabbitMQExtensions.cs
+++ b/src/Components/Aspire.RabbitMQ.Client/AspireRabbitMQExtensions.cs
@@ -9,7 +9,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
-using Microsoft.Extensions.Logging;
using Polly;
using Polly.Retry;
using RabbitMQ.Client;
@@ -40,7 +39,11 @@ public static void AddRabbitMQClient(
string connectionName,
Action? configureSettings = null,
Action? configureConnectionFactory = null)
- => AddRabbitMQClient(builder, configureSettings, configureConnectionFactory, connectionName, serviceKey: null);
+ {
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
+ AddRabbitMQClient(builder, configureSettings, configureConnectionFactory, connectionName, serviceKey: null);
+ }
///
/// Registers as a keyed singleton for the given in the services provided by the .
diff --git a/src/Components/Aspire.Seq/AspireSeqExtensions.cs b/src/Components/Aspire.Seq/AspireSeqExtensions.cs
index 60202fb0b26..c1f1b45c364 100644
--- a/src/Components/Aspire.Seq/AspireSeqExtensions.cs
+++ b/src/Components/Aspire.Seq/AspireSeqExtensions.cs
@@ -32,6 +32,7 @@ public static void AddSeqEndpoint(
Action? configureSettings = null)
{
ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
var settings = new SeqSettings();
settings.Logs.Protocol = OtlpExportProtocol.HttpProtobuf;
@@ -63,13 +64,15 @@ public static void AddSeqEndpoint(
}
builder.Services.Configure(logging => logging.AddProcessor(
- _ => settings.Logs.ExportProcessorType switch {
+ _ => settings.Logs.ExportProcessorType switch
+ {
ExportProcessorType.Batch => new BatchLogRecordExportProcessor(new OtlpLogExporter(settings.Logs)),
_ => new SimpleLogRecordExportProcessor(new OtlpLogExporter(settings.Logs))
}));
builder.Services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddProcessor(
- _ => settings.Traces.ExportProcessorType switch {
+ _ => settings.Traces.ExportProcessorType switch
+ {
ExportProcessorType.Batch => new BatchActivityExportProcessor(new OtlpTraceExporter(settings.Traces)),
_ => new SimpleActivityExportProcessor(new OtlpTraceExporter(settings.Traces))
}));
diff --git a/src/Components/Aspire.StackExchange.Redis.DistributedCaching/AspireRedisDistributedCacheExtensions.cs b/src/Components/Aspire.StackExchange.Redis.DistributedCaching/AspireRedisDistributedCacheExtensions.cs
index 7be0530dcc4..826a0174aa3 100644
--- a/src/Components/Aspire.StackExchange.Redis.DistributedCaching/AspireRedisDistributedCacheExtensions.cs
+++ b/src/Components/Aspire.StackExchange.Redis.DistributedCaching/AspireRedisDistributedCacheExtensions.cs
@@ -29,6 +29,9 @@ public static class AspireRedisDistributedCacheExtensions
///
public static void AddRedisDistributedCache(this IHostApplicationBuilder builder, string connectionName, Action? configureSettings = null, Action? configureOptions = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
builder.AddRedisClient(connectionName, configureSettings, configureOptions);
builder.AddRedisDistributedCacheCore((RedisCacheOptions options, IServiceProvider sp) =>
@@ -52,6 +55,9 @@ public static void AddRedisDistributedCache(this IHostApplicationBuilder builder
///
public static void AddKeyedRedisDistributedCache(this IHostApplicationBuilder builder, string name, Action? configureSettings = null, Action? configureOptions = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(name);
+
builder.AddKeyedRedisClient(name, configureSettings, configureOptions);
builder.AddRedisDistributedCacheCore((RedisCacheOptions options, IServiceProvider sp) =>
diff --git a/src/Components/Aspire.StackExchange.Redis.OutputCaching/AspireRedisOutputCacheExtensions.cs b/src/Components/Aspire.StackExchange.Redis.OutputCaching/AspireRedisOutputCacheExtensions.cs
index caae6c0d969..1625d3a9b19 100644
--- a/src/Components/Aspire.StackExchange.Redis.OutputCaching/AspireRedisOutputCacheExtensions.cs
+++ b/src/Components/Aspire.StackExchange.Redis.OutputCaching/AspireRedisOutputCacheExtensions.cs
@@ -28,6 +28,9 @@ public static class AspireRedisOutputCacheExtensions
///
public static void AddRedisOutputCache(this IHostApplicationBuilder builder, string connectionName, Action? configureSettings = null, Action? configureOptions = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
builder.AddRedisClient(connectionName, configureSettings, configureOptions);
builder.AddRedisOutputCacheCore((RedisOutputCacheOptions options, IServiceProvider sp) =>
@@ -51,6 +54,9 @@ public static void AddRedisOutputCache(this IHostApplicationBuilder builder, str
///
public static void AddKeyedRedisOutputCache(this IHostApplicationBuilder builder, string name, Action? configureSettings = null, Action? configureOptions = null)
{
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentException.ThrowIfNullOrEmpty(name);
+
builder.AddKeyedRedisClient(name, configureSettings, configureOptions);
builder.AddRedisOutputCacheCore((RedisOutputCacheOptions options, IServiceProvider sp) =>
diff --git a/src/Components/Aspire.StackExchange.Redis/AspireRedisExtensions.cs b/src/Components/Aspire.StackExchange.Redis/AspireRedisExtensions.cs
index c24ff7a2b5f..a18366c717d 100644
--- a/src/Components/Aspire.StackExchange.Redis/AspireRedisExtensions.cs
+++ b/src/Components/Aspire.StackExchange.Redis/AspireRedisExtensions.cs
@@ -36,7 +36,11 @@ public static void AddRedisClient(
string connectionName,
Action? configureSettings = null,
Action? configureOptions = null)
- => AddRedisClient(builder, configureSettings, configureOptions, connectionName, serviceKey: null);
+ {
+ ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
+ AddRedisClient(builder, configureSettings, configureOptions, connectionName, serviceKey: null);
+ }
///
/// Registers as a keyed singleton for the given in the services provided by the .
diff --git a/tests/Aspire.Hosting.Oracle.Tests/OraclePublicApiTests.cs b/tests/Aspire.Hosting.Oracle.Tests/OraclePublicApiTests.cs
new file mode 100644
index 00000000000..ca2ca9c4828
--- /dev/null
+++ b/tests/Aspire.Hosting.Oracle.Tests/OraclePublicApiTests.cs
@@ -0,0 +1,254 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire.Hosting.ApplicationModel;
+using Aspire.Hosting.Utils;
+using Xunit;
+
+namespace Aspire.Hosting.Oracle.Tests;
+
+public class OraclePublicApiTests
+{
+ [Fact]
+ public void AddOracleShouldThrowWhenBuilderIsNull()
+ {
+ IDistributedApplicationBuilder builder = null!;
+ const string name = "oracle";
+
+ var action = () => builder.AddOracle(
+ name,
+ default(IResourceBuilder?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddOracleShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ IDistributedApplicationBuilder builder = TestDistributedApplicationBuilder.Create();
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddOracle(
+ name,
+ default(IResourceBuilder?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddDatabaseShouldThrowWhenBuilderIsNull()
+ {
+ IResourceBuilder builder = null!;
+ const string name = "oracle";
+
+ var action = () => builder.AddDatabase(name, default(string?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddDatabaseShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ IDistributedApplicationBuilder builder = TestDistributedApplicationBuilder.Create();
+ var oracle = builder.AddOracle("oracle");
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => oracle.AddDatabase(name, default(string?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+
+ [Fact]
+ public void WithDataVolumeShouldThrowWhenBuilderIsNull()
+ {
+ IResourceBuilder builder = null!;
+
+ var action = () => builder.WithDataVolume();
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Fact]
+ public void WithDataBindMountShouldThrowWhenBuilderIsNull()
+ {
+ IResourceBuilder builder = null!;
+ const string source = "/opt/oracle/oradata";
+
+ var action = () => builder.WithDataBindMount(source);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void WithDataBindMountShouldThrowWhenSourceIsNullOrEmpty(bool isNull)
+ {
+ IDistributedApplicationBuilder builder = TestDistributedApplicationBuilder.Create();
+ var oracle = builder.AddOracle("oracle");
+ var source = isNull ? null! : string.Empty;
+
+ var action = () => oracle.WithDataBindMount(source);
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(source), exception.ParamName);
+ }
+
+ [Fact]
+ public void WithInitBindMountShouldThrowWhenBuilderIsNull()
+ {
+ IResourceBuilder builder = null!;
+ const string source = "/opt/oracle/oradata";
+
+ var action = () => builder.WithInitBindMount(source);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void WithInitBindMountShouldThrowWhenSourceIsNullOrEmpty(bool isNull)
+ {
+ IDistributedApplicationBuilder builder = TestDistributedApplicationBuilder.Create();
+ var oracle = builder.AddOracle("oracle");
+ var source = isNull ? null! : string.Empty;
+
+ var action = () => oracle.WithInitBindMount(source);
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(source), exception.ParamName);
+ }
+
+ [Fact]
+ public void WithDbSetupBindMountShouldThrowWhenBuilderIsNull()
+ {
+ IResourceBuilder builder = null!;
+ const string source = "/opt/oracle/oradata";
+
+ var action = () => builder.WithDbSetupBindMount(source);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void WithDbSetupBindMountShouldThrowWhenSourceIsNullOrEmpty(bool isNull)
+ {
+ IDistributedApplicationBuilder builder = TestDistributedApplicationBuilder.Create();
+ var oracle = builder.AddOracle("oracle");
+ var source = isNull ? null! : string.Empty;
+
+ var action = () => oracle.WithDbSetupBindMount(source);
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(source), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void CtorOracleDatabaseResourceShouldThrowWhenNameIsNull(bool isNull)
+ {
+ var builder = TestDistributedApplicationBuilder.Create();
+ var adminPassword = builder.AddParameter("Password");
+
+ var name = isNull ? null! : string.Empty;
+ const string databaseName = "oracledb";
+ var parent = new OracleDatabaseServerResource("oracledb", adminPassword.Resource);
+
+ var action = () => new OracleDatabaseResource(name, databaseName, parent);
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void CtorOracleDatabaseResourceShouldThrowWhenDatabaseNameIsNull(bool isNull)
+ {
+ var builder = TestDistributedApplicationBuilder.Create();
+ var adminPassword = builder.AddParameter("Password");
+
+ const string name = "oracle";
+ var databaseName = isNull ? null! : string.Empty;
+ var parent = new OracleDatabaseServerResource("oracledb", adminPassword.Resource);
+
+ var action = () => new OracleDatabaseResource(name, databaseName, parent);
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(databaseName), exception.ParamName);
+ }
+
+ [Fact]
+ public void CtorOracleDatabaseResourceShouldThrowWhenParentIsNull()
+ {
+ const string name = "oracle";
+ const string databaseName = "oracledb";
+ OracleDatabaseServerResource parent = null!;
+
+ var action = () => new OracleDatabaseResource(name, databaseName, parent);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(parent), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void CtoOracleDatabaseServerResourceShouldThrowWhenNameIsNull(bool isNull)
+ {
+ var builder = TestDistributedApplicationBuilder.Create();
+ var adminPassword = builder.AddParameter("Password");
+
+ var name = isNull ? null! : string.Empty;
+ var password = adminPassword.Resource;
+
+ var action = () => new OracleDatabaseServerResource(name, password);
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+
+ [Fact]
+ public void CtorOracleDatabaseServerResourceShouldThrowWhenPasswordIsNull()
+ {
+ const string name = "oracle";
+ ParameterResource password = null!;
+
+ var action = () => new OracleDatabaseServerResource(name, password);
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(password), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.Pomelo.EntityFrameworkCore.MySql.Tests/PomeloEntityFrameworkCoreMySqlPublicApiTests.cs b/tests/Aspire.Pomelo.EntityFrameworkCore.MySql.Tests/PomeloEntityFrameworkCoreMySqlPublicApiTests.cs
new file mode 100644
index 00000000000..341830d3983
--- /dev/null
+++ b/tests/Aspire.Pomelo.EntityFrameworkCore.MySql.Tests/PomeloEntityFrameworkCoreMySqlPublicApiTests.cs
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Hosting;
+using Xunit;
+
+namespace Aspire.Pomelo.EntityFrameworkCore.MySql.Tests;
+
+public class PomeloEntityFrameworkCoreMySqlPublicApiTests
+{
+ [Fact]
+ public void AddMySqlDbContextShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "mysql";
+
+ var action = () => builder.AddMySqlDbContext(
+ connectionName,
+ default(Action?),
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddMySqlDbContextShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddMySqlDbContext(
+ connectionName,
+ default(Action?),
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void EnrichMySqlDbContextShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+
+ var action = () => builder.EnrichMySqlDbContext(default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.Qdrant.Client.Tests/QdrantClientPublicApiTests.cs b/tests/Aspire.Qdrant.Client.Tests/QdrantClientPublicApiTests.cs
new file mode 100644
index 00000000000..29fcb51773f
--- /dev/null
+++ b/tests/Aspire.Qdrant.Client.Tests/QdrantClientPublicApiTests.cs
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Hosting;
+using Xunit;
+
+namespace Aspire.Qdrant.Client.Tests;
+
+public class QdrantClientPublicApiTests
+{
+ [Fact]
+ public void AddQdrantClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "qdrant";
+
+ var action = () => builder.AddQdrantClient(
+ connectionName,
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddQdrantClientShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddQdrantClient(
+ connectionName,
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKeyedQdrantClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string name = "qdrant";
+
+ var action = () => builder.AddKeyedQdrantClient(
+ name,
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKeyedQdrantClientShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKeyedQdrantClient(
+ name,
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.RabbitMQ.Client.Tests/RabbitMQClientPublicApiTests.cs b/tests/Aspire.RabbitMQ.Client.Tests/RabbitMQClientPublicApiTests.cs
new file mode 100644
index 00000000000..aa1603794e7
--- /dev/null
+++ b/tests/Aspire.RabbitMQ.Client.Tests/RabbitMQClientPublicApiTests.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Hosting;
+using RabbitMQ.Client;
+using Xunit;
+
+namespace Aspire.RabbitMQ.Client.Tests;
+
+public class RabbitMQClientPublicApiTests
+{
+ [Fact]
+ public void AddRabbitMQClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "rabbitmq";
+
+ var action = () => builder.AddRabbitMQClient(
+ connectionName,
+ default(Action?),
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddRabbitMQClientShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddRabbitMQClient(
+ connectionName,
+ default(Action?),
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKeyedRabbitMQClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string name = "rabbitmq";
+
+ var action = () => builder.AddKeyedRabbitMQClient(
+ name,
+ default(Action?),
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKeyedRabbitMQClientShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKeyedRabbitMQClient(
+ name,
+ default(Action?),
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.Seq.Tests/SeqPublicApiTests.cs b/tests/Aspire.Seq.Tests/SeqPublicApiTests.cs
new file mode 100644
index 00000000000..022a2f12014
--- /dev/null
+++ b/tests/Aspire.Seq.Tests/SeqPublicApiTests.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Hosting;
+using Xunit;
+
+namespace Aspire.Seq.Tests;
+
+public class SeqPublicApiTests
+{
+ [Fact]
+ public void AddSeqEndpointShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "seq";
+
+ var action = () => builder.AddSeqEndpoint(
+ connectionName,
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddSeqEndpointShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddSeqEndpoint(
+ connectionName,
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.StackExchange.Redis.DistributedCaching.Tests/StackExchangeRedisDistributedCachingPublicApiTests.cs b/tests/Aspire.StackExchange.Redis.DistributedCaching.Tests/StackExchangeRedisDistributedCachingPublicApiTests.cs
new file mode 100644
index 00000000000..98e96b1c5a4
--- /dev/null
+++ b/tests/Aspire.StackExchange.Redis.DistributedCaching.Tests/StackExchangeRedisDistributedCachingPublicApiTests.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Hosting;
+using StackExchange.Redis;
+using Xunit;
+
+namespace Aspire.StackExchange.Redis.DistributedCaching.Tests;
+
+public class StackExchangeRedisDistributedCachingPublicApiTests
+{
+ [Fact]
+ public void AddRedisDistributedCacheShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "redis";
+
+ var action = () => builder.AddRedisDistributedCache(
+ connectionName,
+ default(Action?),
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddRedisDistributedCacheShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddRedisDistributedCache(
+ connectionName,
+ default(Action?),
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKeyedRedisDistributedCacheShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string name = "redis";
+
+ var action = () => builder.AddKeyedRedisDistributedCache(
+ name,
+ default(Action?),
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKeyedRedisDistributedCacheShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKeyedRedisDistributedCache(
+ name,
+ default(Action?),
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.StackExchange.Redis.OutputCaching.Tests/StackExchangeRedisOutputCachingPublicApiTests.cs b/tests/Aspire.StackExchange.Redis.OutputCaching.Tests/StackExchangeRedisOutputCachingPublicApiTests.cs
new file mode 100644
index 00000000000..20ab1a136e6
--- /dev/null
+++ b/tests/Aspire.StackExchange.Redis.OutputCaching.Tests/StackExchangeRedisOutputCachingPublicApiTests.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Hosting;
+using StackExchange.Redis;
+using Xunit;
+
+namespace Aspire.StackExchange.Redis.OutputCaching.Tests;
+
+public class StackExchangeRedisOutputCachingPublicApiTests
+{
+ [Fact]
+ public void AddRedisOutputCacheShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "redis";
+
+ var action = () => builder.AddRedisOutputCache(
+ connectionName,
+ default(Action?),
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddRedisOutputCacheShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddRedisOutputCache(
+ connectionName,
+ default(Action?),
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKeyedRedisOutputCacheShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string name = "redis";
+
+ var action = () => builder.AddKeyedRedisOutputCache(
+ name,
+ default(Action?),
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKeyedRedisOutputCacheShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKeyedRedisOutputCache(
+ name,
+ default(Action?),
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+}
diff --git a/tests/Aspire.StackExchange.Redis.Tests/StackExchangeRedisPublicApiTests.cs b/tests/Aspire.StackExchange.Redis.Tests/StackExchangeRedisPublicApiTests.cs
new file mode 100644
index 00000000000..ce225fe9390
--- /dev/null
+++ b/tests/Aspire.StackExchange.Redis.Tests/StackExchangeRedisPublicApiTests.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Extensions.Hosting;
+using StackExchange.Redis;
+using Xunit;
+
+namespace Aspire.StackExchange.Redis.Tests;
+
+public class StackExchangeRedisPublicApiTests
+{
+ [Fact]
+ public void AddRedisClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string connectionName = "redis";
+
+ var action = () => builder.AddRedisClient(
+ connectionName,
+ default(Action?),
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddRedisClientShouldThrowWhenConnectionNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var connectionName = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddRedisClient(
+ connectionName,
+ default(Action?),
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(connectionName), exception.ParamName);
+ }
+
+ [Fact]
+ public void AddKeyedRedisClientShouldThrowWhenBuilderIsNull()
+ {
+ IHostApplicationBuilder builder = null!;
+ const string name = "redis";
+
+ var action = () => builder.AddKeyedRedisClient(
+ name,
+ default(Action?),
+ default(Action?));
+
+ var exception = Assert.Throws(action);
+ Assert.Equal(nameof(builder), exception.ParamName);
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public void AddKeyedRedisClientShouldThrowWhenNameIsNullOrEmpty(bool isNull)
+ {
+ IHostApplicationBuilder builder = new HostApplicationBuilder();
+ var name = isNull ? null! : string.Empty;
+
+ var action = () => builder.AddKeyedRedisClient(
+ name,
+ default(Action?),
+ default(Action?));
+
+ var exception = isNull
+ ? Assert.Throws(action)
+ : Assert.Throws(action);
+ Assert.Equal(nameof(name), exception.ParamName);
+ }
+}