diff --git a/src/CommunityToolkit.Aspire.Hosting.SurrealDb/CommunityToolkit.Aspire.Hosting.SurrealDb.csproj b/src/CommunityToolkit.Aspire.Hosting.SurrealDb/CommunityToolkit.Aspire.Hosting.SurrealDb.csproj
index ae8521bdc..f8b7e8ad9 100644
--- a/src/CommunityToolkit.Aspire.Hosting.SurrealDb/CommunityToolkit.Aspire.Hosting.SurrealDb.csproj
+++ b/src/CommunityToolkit.Aspire.Hosting.SurrealDb/CommunityToolkit.Aspire.Hosting.SurrealDb.csproj
@@ -18,4 +18,8 @@
+
+
+
+
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests.csproj b/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests.csproj
index b45e2004d..7c8909851 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests.csproj
+++ b/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests.csproj
@@ -4,10 +4,6 @@
CommunityToolkit.Aspire.Hosting.SurrealDb.Tests
-
-
-
-
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbFunctionalTests.cs b/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbFunctionalTests.cs
deleted file mode 100644
index 6dc0f884e..000000000
--- a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbFunctionalTests.cs
+++ /dev/null
@@ -1,447 +0,0 @@
-// 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;
-using Aspire.Hosting.Utils;
-using Bogus;
-using CommunityToolkit.Aspire.Testing;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.Diagnostics.HealthChecks;
-using Microsoft.Extensions.Hosting;
-using Polly;
-using SurrealDb.Net;
-using SurrealDb.Net.Exceptions;
-using System.ComponentModel.DataAnnotations.Schema;
-using SurrealRecord = SurrealDb.Net.Models.Record;
-
-namespace CommunityToolkit.Aspire.Hosting.SurrealDb.Tests;
-
-[RequiresDocker]
-public class SurrealDbFunctionalTests(ITestOutputHelper testOutputHelper)
-{
- private const int _generatedTodoCount = 10;
- private static readonly Todo[] _todoList;
-
- static SurrealDbFunctionalTests()
- {
- _todoList = [.. new TodoFaker().Generate(_generatedTodoCount)];
-
- int index = 0;
- foreach (var todo in _todoList)
- {
- todo.Id = (Todo.Table, (++index).ToString());
- }
- }
-
- [Fact]
- public async Task VerifySurrealDbResource()
- {
- using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
- var ct = cts.Token;
- await using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
-
- var surrealServer = builder.AddSurrealServer("surreal");
-
- var db = surrealServer
- .AddNamespace("ns")
- .AddDatabase("db");
-
- await using var app = builder.Build();
-
- await app.StartAsync(ct);
-
- await app.ResourceNotifications.WaitForResourceHealthyAsync(db.Resource.Name, ct);
-
- var hb = Host.CreateApplicationBuilder();
-
- hb.Configuration[$"ConnectionStrings:{db.Resource.Name}"] = await db.Resource.ConnectionStringExpression.GetValueAsync(ct);
-
- hb.AddSurrealClient(db.Resource.Name);
-
- using var host = hb.Build();
-
- await host.StartAsync(ct);
-
- await using var scope = host.Services.CreateAsyncScope();
- await using var client = scope.ServiceProvider.GetRequiredService();
-
- await CreateTestData(client, ct);
- await AssertTestData(client, ct);
- }
-
- [Theory]
- [InlineData(true)]
- [InlineData(false)]
- public async Task WithDataShouldPersistStateBetweenUsages(bool useVolume)
- {
- using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
- var ct = cts.Token;
-
- string? volumeName = null;
- string? bindMountPath = null;
-
- const string databasePath = "surrealkv://data/db.db";
-
- try
- {
- using var builder1 = TestDistributedApplicationBuilder.Create(testOutputHelper);
-
- var password1 = builder1.AddParameter("surreal-password", secret: true);
- password1.Resource.Default = new PasswordConstantDefault();
-
- var surrealServer1 =
- builder1.AddSurrealServer("surreal", path: databasePath, password: password1);
-
- var db1 = surrealServer1
- .AddNamespace("ns")
- .AddDatabase("db");
-
- if (useVolume)
- {
- // Use a deterministic volume name to prevent them from exhausting the machines if deletion fails
- volumeName = VolumeNameGenerator.Generate(surrealServer1,
- nameof(WithDataShouldPersistStateBetweenUsages));
-
- // if the volume already exists (because of a crashing previous run), delete it
- DockerUtils.AttemptDeleteDockerVolume(volumeName, throwOnFailure: true);
- surrealServer1.WithDataVolume(volumeName);
- }
- else
- {
- bindMountPath = Directory.CreateTempSubdirectory().FullName;
- surrealServer1.WithDataBindMount(bindMountPath);
-
- if (!OperatingSystem.IsWindows())
- {
- File.SetUnixFileMode(bindMountPath,
- UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute |
- UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute);
- }
- }
-
- using (var app = builder1.Build())
- {
- await app.StartAsync(ct);
-
- await app.ResourceNotifications.WaitForResourceHealthyAsync(surrealServer1.Resource.Name, ct);
- await app.ResourceNotifications.WaitForResourceHealthyAsync(db1.Resource.Name, ct);
-
- try
- {
- var hb = Host.CreateApplicationBuilder();
-
- hb.Configuration[$"ConnectionStrings:{db1.Resource.Name}"] =
- await db1.Resource.ConnectionStringExpression.GetValueAsync(ct);
-
- hb.AddSurrealClient(db1.Resource.Name);
-
- using var host = hb.Build();
- await host.StartAsync(ct);
-
- await using var scope1 = host.Services.CreateAsyncScope();
- await using var client = scope1.ServiceProvider.GetRequiredService();
- await CreateTestData(client, ct);
- await AssertTestData(client, ct);
- }
- finally
- {
- // Stops the container, or the Volume would still be in use
- await app.StopAsync(ct);
- }
- }
-
- using var builder2 = TestDistributedApplicationBuilder.Create(testOutputHelper);
-
- var password2 = builder2.AddParameter("surreal-password", secret: true);
- password2.Resource.Default = new PasswordConstantDefault();
-
- var surrealServer2 =
- builder2.AddSurrealServer("surreal", path: databasePath, password: password2);
-
- var db2 = surrealServer2
- .AddNamespace("ns")
- .AddDatabase("db");
-
- if (useVolume)
- {
- surrealServer2.WithDataVolume(volumeName);
- }
- else
- {
- surrealServer2.WithDataBindMount(bindMountPath!);
- }
-
- using (var app = builder2.Build())
- {
- await app.StartAsync(ct);
-
- await app.ResourceNotifications.WaitForResourceHealthyAsync(surrealServer2.Resource.Name, ct);
- await app.ResourceNotifications.WaitForResourceHealthyAsync(db2.Resource.Name, ct);
-
- try
- {
- var hb = Host.CreateApplicationBuilder();
-
- hb.Configuration[$"ConnectionStrings:{db2.Resource.Name}"] =
- await db2.Resource.ConnectionStringExpression.GetValueAsync(ct);
-
- hb.AddSurrealClient(db2.Resource.Name);
-
- using var host = hb.Build();
- await host.StartAsync(ct);
- await using var scope2 = host.Services.CreateAsyncScope();
- await using var client = scope2.ServiceProvider.GetRequiredService();
- await AssertTestData(client, ct);
- }
- finally
- {
- // Stops the container, or the Volume would still be in use
- await app.StopAsync(ct);
- }
- }
- }
- finally
- {
- if (volumeName is not null)
- {
- DockerUtils.AttemptDeleteDockerVolume(volumeName);
- }
-
- if (bindMountPath is not null)
- {
- try
- {
- Directory.Delete(bindMountPath, recursive: true);
- }
- catch
- {
- // Don't fail test if we can't clean the temporary folder
- }
- }
- }
- }
-
- [Fact]
- public async Task VerifyWaitForOnSurrealDbBlocksDependentResources()
- {
- using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(10));
- await using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
-
- var healthCheckTcs = new TaskCompletionSource();
- builder.Services.AddHealthChecks().AddAsyncCheck("blocking_check", () => healthCheckTcs.Task);
-
- var resource = builder.AddSurrealServer("resource")
- .WithHealthCheck("blocking_check");
-
- var dependentResource = builder.AddSurrealServer("dependentresource")
- .WaitFor(resource);
-
- await using var app = builder.Build();
-
- var pendingStart = app.StartAsync(cts.Token);
-
- var rns = app.Services.GetRequiredService();
-
- await rns.WaitForResourceAsync(resource.Resource.Name, KnownResourceStates.Running, cts.Token);
-
- await rns.WaitForResourceAsync(dependentResource.Resource.Name, KnownResourceStates.Waiting, cts.Token);
-
- healthCheckTcs.SetResult(HealthCheckResult.Healthy());
-
- await rns.WaitForResourceAsync(resource.Resource.Name, re => re.Snapshot.HealthStatus == HealthStatus.Healthy, cts.Token);
-
- await rns.WaitForResourceAsync(dependentResource.Resource.Name, KnownResourceStates.Running, cts.Token);
-
- await pendingStart;
-
- await app.StopAsync(cts.Token);
- }
-
- [Fact(Skip = "Feature is unstable and blocking the release")]
- public async Task VerifyWithInitFiles()
- {
- // Creates a script that should be executed when the container is initialized.
-
- using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(10));
- var pipeline = new ResiliencePipelineBuilder()
- .AddRetry(new() { MaxRetryAttempts = 10, BackoffType = DelayBackoffType.Linear, Delay = TimeSpan.FromSeconds(2), ShouldHandle = new PredicateBuilder().Handle() })
- .Build();
-
- var initDirPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
-
- Directory.CreateDirectory(initDirPath);
-
- var initFilePath = Path.Combine(initDirPath, "init.surql");
-
- var surrealNsName = "ns1";
- var surrealDbName = "db1";
-
- try
- {
- await File.WriteAllTextAsync(
- initFilePath,
- $"""
- USE NS {surrealNsName};
- USE DB {surrealDbName};
-
- CREATE car SET Brand = "BatMobile";
- """,
- cts.Token
- );
-
- await using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
-
-#pragma warning disable CTASPIRE002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
- var surrealServer = builder
- .AddSurrealServer("surreal")
- .WithInitFiles(initFilePath);
-#pragma warning restore CTASPIRE002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
-
- var ns = surrealServer.AddNamespace(surrealNsName);
- var db = ns.AddDatabase(surrealDbName);
-
- await using var app = builder.Build();
-
- await app.StartAsync(cts.Token);
-
- var rns = app.Services.GetRequiredService();
-
- await rns.WaitForResourceAsync(db.Resource.Name, KnownResourceStates.Running, cts.Token);
-
- var hb = Host.CreateApplicationBuilder();
-
- hb.Configuration.AddInMemoryCollection(new Dictionary
- {
- [$"ConnectionStrings:{db.Resource.Name}"] = await db.Resource.ConnectionStringExpression.GetValueAsync(cts.Token)
- });
-
- hb.AddSurrealClient(db.Resource.Name);
-
- using var host = hb.Build();
-
- await host.StartAsync(cts.Token);
-
- // Wait until the database is available
- await rns.WaitForResourceHealthyAsync(db.Resource.Name, cts.Token);
-
- await pipeline.ExecuteAsync(async token =>
- {
- await using var client = host.Services.GetRequiredService();
-
- var cars = (await client.Select(Car.Table, token)).ToList();
- var car = Assert.Single(cars);
- Assert.Equal("BatMobile", car.Brand);
- }, cts.Token);
- }
- finally
- {
- try
- {
- Directory.Delete(initDirPath);
- }
- catch
- {
- // Don't fail test if we can't clean the temporary folder
- }
- }
- }
-
- [Fact(Skip = "Feature is unstable and blocking the release")]
- public async Task AddDatabaseCreatesDatabaseWithCustomScript()
- {
- using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
-
- using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper);
-
- var surrealNsName = "ns1";
- var surrealDbName = "db1";
-
- var surreal = builder.AddSurrealServer("surreal");
-
-#pragma warning disable CTASPIRE002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
- var db = surreal
- .AddNamespace(surrealNsName)
- .AddDatabase(surrealDbName)
- .WithCreationScript(
- $"""
- DEFINE DATABASE IF NOT EXISTS {surrealDbName};
- USE DATABASE {surrealDbName};
-
- DEFINE TABLE todo;
- DEFINE FIELD title ON todo TYPE string;
- DEFINE FIELD due_by ON todo TYPE datetime;
- DEFINE FIELD is_complete ON todo TYPE bool;
- """
- );
-#pragma warning restore CTASPIRE002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
-
- using var app = builder.Build();
-
- await app.StartAsync(cts.Token);
-
- var hb = Host.CreateApplicationBuilder();
-
- hb.Configuration[$"ConnectionStrings:{db.Resource.Name}"] = await db.Resource.ConnectionStringExpression.GetValueAsync(default);
-
- hb.AddSurrealClient(db.Resource.Name);
-
- using var host = hb.Build();
-
- await host.StartAsync();
-
- await app.ResourceNotifications.WaitForResourceHealthyAsync(db.Resource.Name, cts.Token);
-
- await using var scope = host.Services.CreateAsyncScope();
- await using var client = scope.ServiceProvider.GetRequiredService();
-
- await CreateTestData(client, cts.Token);
- await AssertTestData(client, cts.Token);
- }
-
- private static async Task CreateTestData(SurrealDbSession client, CancellationToken ct)
- {
- await client.Insert(Todo.Table, _todoList, ct);
- }
-
- private static async Task AssertTestData(SurrealDbSession client, CancellationToken ct)
- {
- var records = await client.Select(Todo.Table, ct);
- Assert.Equal(_generatedTodoCount, records.Count());
-
- var firstRecord = await client.Select((Todo.Table, "1"), ct);
- Assert.NotNull(firstRecord);
- Assert.Equivalent(firstRecord, _todoList[0]);
- }
-
- private sealed class Todo : SurrealRecord
- {
- internal const string Table = "todo";
-
- [Column("title")]
- public string? Title { get; set; }
-
- [Column("due_by")]
- public DateOnly? DueBy { get; set; } = null;
-
- [Column("is_complete")]
- public bool IsComplete { get; set; } = false;
- }
-
- private class TodoFaker : Faker
- {
- public TodoFaker()
- {
- RuleFor(o => o.Title, f => f.Lorem.Sentence());
- RuleFor(o => o.DueBy, f => f.Date.SoonDateOnly());
- RuleFor(o => o.IsComplete, f => f.Random.Bool());
- }
- }
-
- private sealed class Car : SurrealRecord
- {
- internal const string Table = "car";
-
- [Column("brand")]
- public string Brand { get; set; } = string.Empty;
- }
-}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbPublicApiTests.cs b/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbPublicApiTests.cs
index a1b025547..81209c95d 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbPublicApiTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/SurrealDbPublicApiTests.cs
@@ -4,6 +4,7 @@
using Aspire.Hosting;
using Aspire.Hosting.Utils;
using Microsoft.Extensions.Logging;
+using CommunityToolkit.Aspire.Testing;
namespace CommunityToolkit.Aspire.Hosting.SurrealDb.Tests;
@@ -21,6 +22,22 @@ public void AddSurrealServerContainerShouldThrowWhenBuilderIsNull()
Assert.Equal(nameof(builder), exception.ParamName);
}
+ [Fact]
+ public void AddDatabaseShouldCreateHealthCheckAnnotation()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ builder.AddSurrealServer("surreal")
+ .AddNamespace("ns")
+ .AddDatabase("db");
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+ var resource = Assert.Single(appModel.Resources.OfType());
+
+ var healthCheck = Assert.Single(resource.Annotations.OfType());
+ Assert.Equal("surreal_ns_db_check", healthCheck.Key);
+ }
+
[Fact]
public void AddSurrealServerContainerShouldThrowWhenNameIsNull()
{
@@ -90,9 +107,9 @@ public void WithDataVolumeShouldThrowWhenBuilderIsNull()
public void WithDataShouldThrowWhenBuilderIsNull(bool useVolume)
{
IResourceBuilder builder = null!;
-
+
Func>? action = null;
-
+
if (useVolume)
{
action = () => builder.WithDataVolume();
@@ -100,28 +117,61 @@ public void WithDataShouldThrowWhenBuilderIsNull(bool useVolume)
else
{
const string source = "/data";
-
+
action = () => builder.WithDataBindMount(source);
}
-
+
var exception = Assert.Throws(action);
Assert.Equal(nameof(builder), exception.ParamName);
}
-
+
[Fact]
public void WithDataBindMountShouldThrowWhenSourceIsNull()
{
var builder = TestDistributedApplicationBuilder.Create();
var resourceBuilder = builder.AddSurrealServer("surreal");
-
+
string source = null!;
-
+
var action = () => resourceBuilder.WithDataBindMount(source);
-
+
var exception = Assert.Throws(action);
Assert.Equal(nameof(source), exception.ParamName);
}
-
+
+ [Fact]
+ public void WithDataVolumeShouldCreateVolumeMountAnnotation()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ builder.AddSurrealServer("surreal").WithDataVolume("surreal-data");
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+ var resource = Assert.Single(appModel.Resources.OfType());
+
+ var mountAnnotation = Assert.Single(resource.Annotations.OfType());
+ Assert.Equal(ContainerMountType.Volume, mountAnnotation.Type);
+ Assert.Equal("surreal-data", mountAnnotation.Source);
+ Assert.Equal("/data", mountAnnotation.Target);
+ }
+
+ [Fact]
+ public void WithDataBindMountShouldCreateBindMountAnnotation()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+ var source = Path.GetTempPath();
+ builder.AddSurrealServer("surreal").WithDataBindMount(source);
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+ var resource = Assert.Single(appModel.Resources.OfType());
+
+ var mountAnnotation = Assert.Single(resource.Annotations.OfType());
+ Assert.Equal(ContainerMountType.BindMount, mountAnnotation.Type);
+ Assert.Equal(source, mountAnnotation.Source);
+ Assert.Equal("/data", mountAnnotation.Target);
+ }
+
[Fact(Skip = "Feature is unstable and blocking the release")]
public void WithInitFilesShouldThrowWhenBuilderIsNull()
{
@@ -154,7 +204,38 @@ public void WithInitFilesShouldThrowWhenSourceIsNullOrEmpty(bool isNull)
: Assert.Throws(action);
Assert.Equal(nameof(source), exception.ParamName);
}
-
+
+ [Fact]
+ public async Task WithInitFilesShouldAddContainerFilesAndEnvironmentVariable()
+ {
+ var initDirectory = Directory.CreateTempSubdirectory();
+ var initFilePath = Path.Combine(initDirectory.FullName, "init.surql");
+ await File.WriteAllTextAsync(initFilePath, "DEFINE TABLE todo;");
+
+ try
+ {
+ var builder = DistributedApplication.CreateBuilder();
+#pragma warning disable CTASPIRE002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+ builder.AddSurrealServer("surreal").WithInitFiles(initFilePath);
+#pragma warning restore CTASPIRE002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+ var resource = Assert.Single(appModel.Resources.OfType());
+
+ var containerFilesAnnotation = Assert.Single(resource.Annotations.OfType());
+ Assert.Equal("/docker-entrypoint-initdb.d", containerFilesAnnotation.DestinationPath);
+
+ var environmentVariables = await resource.GetEnvironmentVariablesAsync();
+ Assert.True(environmentVariables.TryGetValue("SURREAL_IMPORT_FILE", out var importFile));
+ Assert.Equal("/docker-entrypoint-initdb.d/init.surql", importFile);
+ }
+ finally
+ {
+ Directory.Delete(initDirectory.FullName, recursive: true);
+ }
+ }
+
[Fact]
public void WithLogLevelShouldThrowWhenBuilderIsNull()
{
@@ -168,6 +249,27 @@ public void WithLogLevelShouldThrowWhenBuilderIsNull()
Assert.Equal(nameof(builder), exception.ParamName);
}
+ [Fact]
+ public void WithCreationScriptShouldCreateDatabaseScriptAnnotation()
+ {
+ const string script = "DEFINE TABLE todo;";
+
+ var builder = DistributedApplication.CreateBuilder();
+#pragma warning disable CTASPIRE002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+ builder.AddSurrealServer("surreal")
+ .AddNamespace("ns")
+ .AddDatabase("db")
+ .WithCreationScript(script);
+#pragma warning restore CTASPIRE002 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+ var resource = Assert.Single(appModel.Resources.OfType());
+
+ var scriptAnnotation = Assert.Single(resource.Annotations.OfType());
+ Assert.Equal(script, scriptAnnotation.Script);
+ }
+
[Fact]
public void WithSurrealistShouldThrowWhenBuilderIsNull()
{
@@ -279,13 +381,13 @@ public void CtorSurrealServerDatabaseResourceShouldThrowWhenDatabaseNameIsEmpty(
string name = "surreal";
string namespaceName = "ns";
- string databaseName = null!;
+ string databaseName = "";
var password = ParameterResourceBuilderExtensions.CreateDefaultPasswordParameter(distributedApplicationBuilder, "password", special: false);
var parent = new SurrealDbServerResource("surreal", null, password);
var nsParent = new SurrealDbNamespaceResource("ns", namespaceName, parent);
var action = () => new SurrealDbDatabaseResource(name, databaseName, nsParent);
- var exception = Assert.Throws(action);
+ var exception = Assert.Throws(action);
Assert.Equal(nameof(databaseName), exception.ParamName);
}