diff --git a/src/DotNet.Testcontainers.Tests/DotNet.Testcontainers.Tests.csproj b/src/DotNet.Testcontainers.Tests/DotNet.Testcontainers.Tests.csproj
index cdc992286..69405ed40 100644
--- a/src/DotNet.Testcontainers.Tests/DotNet.Testcontainers.Tests.csproj
+++ b/src/DotNet.Testcontainers.Tests/DotNet.Testcontainers.Tests.csproj
@@ -7,6 +7,7 @@
+
diff --git a/src/DotNet.Testcontainers.Tests/Unit/DatabaseContainerTest.cs b/src/DotNet.Testcontainers.Tests/Unit/DatabaseContainerTest.cs
index 38db160ea..47ee92506 100644
--- a/src/DotNet.Testcontainers.Tests/Unit/DatabaseContainerTest.cs
+++ b/src/DotNet.Testcontainers.Tests/Unit/DatabaseContainerTest.cs
@@ -3,6 +3,8 @@ namespace DotNet.Testcontainers.Tests.Unit
using System.Threading.Tasks;
using DotNet.Testcontainers.Core.Builder;
using DotNet.Testcontainers.Core.Containers.Database;
+ using DotNet.Testcontainers.Core.Models;
+ using Npgsql;
using Xunit;
public class DatabaseContainerTest
@@ -10,18 +12,31 @@ public class DatabaseContainerTest
[Fact]
public async Task PostgreSqlContainer()
{
- var database = string.Empty;
-
- var username = string.Empty;
-
- var password = string.Empty;
-
var testcontainersBuilder = new TestcontainersBuilder()
- .WithDatabase(database, username, password);
+ .WithDatabase(new DatabaseConfiguration
+ {
+ Database = "db",
+ Username = "postgres",
+ Password = "postgres",
+ });
using (var testcontainer = testcontainersBuilder.Build())
{
await testcontainer.StartAsync();
+
+ /*
+ using (var connection = new NpgsqlConnection(testcontainer.ConnectionString))
+ {
+ connection.Open();
+
+ using (var cmd = new NpgsqlCommand())
+ {
+ cmd.Connection = connection;
+ cmd.CommandText = "SELECT 1";
+ cmd.ExecuteReader();
+ }
+ }
+ */
}
}
}
diff --git a/src/DotNet.Testcontainers.Tests/Unit/TestcontainersTest.cs b/src/DotNet.Testcontainers.Tests/Unit/TestcontainersContainerTest.cs
similarity index 99%
rename from src/DotNet.Testcontainers.Tests/Unit/TestcontainersTest.cs
rename to src/DotNet.Testcontainers.Tests/Unit/TestcontainersContainerTest.cs
index 66cbb7f5a..a947a07fa 100644
--- a/src/DotNet.Testcontainers.Tests/Unit/TestcontainersTest.cs
+++ b/src/DotNet.Testcontainers.Tests/Unit/TestcontainersContainerTest.cs
@@ -10,7 +10,7 @@ namespace DotNet.Testcontainers.Tests.Unit
using Xunit;
using static LanguageExt.Prelude;
- public static class TestcontainersTest
+ public static class TestcontainersContainerTest
{
private static readonly string TempDir = Environment.GetEnvironmentVariable("AGENT_TEMPDIRECTORY") ?? "."; // We cannot use `Path.GetTempPath()` on macOS, see: https://github.com/common-workflow-language/cwltool/issues/328
diff --git a/src/DotNet.Testcontainers.Tests/Unit/TestcontainersWaitStrategyTest.cs b/src/DotNet.Testcontainers.Tests/Unit/TestcontainersWaitStrategyTest.cs
index bc395a5a5..1c8a4c33f 100644
--- a/src/DotNet.Testcontainers.Tests/Unit/TestcontainersWaitStrategyTest.cs
+++ b/src/DotNet.Testcontainers.Tests/Unit/TestcontainersWaitStrategyTest.cs
@@ -35,7 +35,7 @@ protected override async Task Until()
public class Timeout : WaitStrategy
{
[Fact]
- public async Task WhileAfter5ms()
+ public async Task WhileAfter1ms()
{
await Assert.ThrowsAsync(async () =>
{
@@ -44,7 +44,7 @@ await Assert.ThrowsAsync(async () =>
}
[Fact]
- public async Task UntilAfter5ms()
+ public async Task UntilAfter1ms()
{
await Assert.ThrowsAsync(async () =>
{
diff --git a/src/DotNet.Testcontainers/Core/Builder/TestcontainersBuilder.cs b/src/DotNet.Testcontainers/Core/Builder/TestcontainersBuilder.cs
index bd38f891b..6c73ef465 100644
--- a/src/DotNet.Testcontainers/Core/Builder/TestcontainersBuilder.cs
+++ b/src/DotNet.Testcontainers/Core/Builder/TestcontainersBuilder.cs
@@ -103,7 +103,7 @@ public ITestcontainersBuilder WithExposedPort(string port)
{
return Build(this, new TestcontainersConfiguration
{
- Container = new ContainerConfiguration { Labels = new Dictionary { { port, port } } },
+ Container = new ContainerConfiguration { ExposedPorts = new Dictionary { { port, port } } },
});
}
diff --git a/src/DotNet.Testcontainers/Core/Builder/TestcontainersBuilderExtensions.cs b/src/DotNet.Testcontainers/Core/Builder/TestcontainersBuilderExtensions.cs
deleted file mode 100644
index 52b6caebc..000000000
--- a/src/DotNet.Testcontainers/Core/Builder/TestcontainersBuilderExtensions.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-namespace DotNet.Testcontainers.Core.Builder
-{
- using DotNet.Testcontainers.Core.Containers.Database;
-
- public static class TestcontainersBuilderExtensions
- {
- public static ITestcontainersBuilder WithDatabase(this ITestcontainersBuilder builder, string database, string username, string password)
- where T : PostgreSqlContainer
- {
- return builder
- .WithImage("postgres")
- .WithCommand("postgres")
- .WithExposedPort(5432)
- .WithEnvironment("POSTGRES_DB", database)
- .WithEnvironment("POSTGRES_USER", username)
- .WithEnvironment("POSTGRES_PASSWORD", password)
- .ConfigureContainer((container) =>
- {
- container.Database = database;
- container.Username = username;
- container.Password = password;
- });
- }
- }
-}
diff --git a/src/DotNet.Testcontainers/Core/Builder/TestcontainersBuilderPostgreSqlExtension.cs b/src/DotNet.Testcontainers/Core/Builder/TestcontainersBuilderPostgreSqlExtension.cs
new file mode 100644
index 000000000..73ddfd676
--- /dev/null
+++ b/src/DotNet.Testcontainers/Core/Builder/TestcontainersBuilderPostgreSqlExtension.cs
@@ -0,0 +1,37 @@
+namespace DotNet.Testcontainers.Core.Builder
+{
+ using DotNet.Testcontainers.Core.Containers.Database;
+ using DotNet.Testcontainers.Core.Models;
+
+ public static class TestcontainersBuilderPostgreSqlExtension
+ {
+ private const string DefaultImage = "postgres:11.2";
+
+ private const string DefaultPort = "5432";
+
+ private const string Database = "POSTGRES_DB";
+
+ private const string Username = "POSTGRES_USER";
+
+ private const string Password = "POSTGRES_PASSWORD";
+
+ public static ITestcontainersBuilder WithDatabase(this ITestcontainersBuilder builder, DatabaseConfiguration configuration)
+ where T : PostgreSqlContainer
+ {
+ return builder
+ .WithImage(DefaultImage)
+ .WithPortBinding(DefaultPort)
+ .WithEnvironment(Database, configuration.Database)
+ .WithEnvironment(Username, configuration.Username)
+ .WithEnvironment(Password, configuration.Password)
+ .ConfigureContainer((container) =>
+ {
+ container.Hostname = configuration.Hostname;
+ container.Port = configuration.Port;
+ container.Database = configuration.Database;
+ container.Username = configuration.Username;
+ container.Password = configuration.Password;
+ });
+ }
+ }
+}
diff --git a/src/DotNet.Testcontainers/Core/Containers/Database/DatabaseContainer.cs b/src/DotNet.Testcontainers/Core/Containers/Database/DatabaseContainer.cs
index c54771e76..094c49b9f 100644
--- a/src/DotNet.Testcontainers/Core/Containers/Database/DatabaseContainer.cs
+++ b/src/DotNet.Testcontainers/Core/Containers/Database/DatabaseContainer.cs
@@ -5,10 +5,14 @@ namespace DotNet.Testcontainers.Core.Containers.Database
public abstract class DatabaseContainer : TestcontainersContainer
{
- internal DatabaseContainer(TestcontainersConfiguration configuration) : base(configuration)
+ protected DatabaseContainer(TestcontainersConfiguration configuration) : base(configuration)
{
}
+ public virtual string Hostname { get; set; }
+
+ public virtual string Port { get; set; }
+
public virtual string Database { get; set; }
public virtual string Username { get; set; }
diff --git a/src/DotNet.Testcontainers/Core/Containers/Database/PostgreSqlContainer.cs b/src/DotNet.Testcontainers/Core/Containers/Database/PostgreSqlContainer.cs
index 152acbfb3..3315b284d 100644
--- a/src/DotNet.Testcontainers/Core/Containers/Database/PostgreSqlContainer.cs
+++ b/src/DotNet.Testcontainers/Core/Containers/Database/PostgreSqlContainer.cs
@@ -8,6 +8,6 @@ internal PostgreSqlContainer(TestcontainersConfiguration configuration) : base(c
{
}
- public override string ConnectionString => $"Server=127.0.0.1;Port=5432;Database={this.Database};User Id={this.Username};Password={this.Password};";
+ public override string ConnectionString => $"Server={this.Hostname};Port={this.Port};Database={this.Database};User Id={this.Username};Password={this.Password};";
}
}
diff --git a/src/DotNet.Testcontainers/Core/Containers/TestcontainersContainer.cs b/src/DotNet.Testcontainers/Core/Containers/TestcontainersContainer.cs
index 5b66c1aff..22729d92a 100644
--- a/src/DotNet.Testcontainers/Core/Containers/TestcontainersContainer.cs
+++ b/src/DotNet.Testcontainers/Core/Containers/TestcontainersContainer.cs
@@ -19,7 +19,7 @@ public class TestcontainersContainer : IDockerContainer
private Option container = None;
- internal TestcontainersContainer(TestcontainersConfiguration configuration)
+ protected TestcontainersContainer(TestcontainersConfiguration configuration)
{
this.Configuration = configuration;
}
diff --git a/src/DotNet.Testcontainers/Core/Mapper/TestcontainersConfigurationConverter.cs b/src/DotNet.Testcontainers/Core/Mapper/TestcontainersConfigurationConverter.cs
index a5cd94e89..8ed19fe70 100644
--- a/src/DotNet.Testcontainers/Core/Mapper/TestcontainersConfigurationConverter.cs
+++ b/src/DotNet.Testcontainers/Core/Mapper/TestcontainersConfigurationConverter.cs
@@ -33,7 +33,7 @@ private class ToList : CollectionConverter>
{
public override IList Convert(IReadOnlyCollection source)
{
- return source.ToList();
+ return source?.ToList();
}
}
@@ -41,7 +41,7 @@ private class ToDictionary : DictionaryConverter>
{
public override IDictionary Convert(IReadOnlyDictionary source)
{
- return source.ToDictionary(item => item.Key, item => item.Value);
+ return source?.ToDictionary(item => item.Key, item => item.Value);
}
}
@@ -49,7 +49,7 @@ private class ToMappedList : DictionaryConverter>
{
public override IList Convert(IReadOnlyDictionary source)
{
- return source.Select(item => $"{item.Key}={item.Value}").ToList();
+ return source?.Select(item => $"{item.Key}={item.Value}").ToList();
}
}
@@ -61,7 +61,7 @@ public ToExposedPorts() : base("ExposedPorts")
public override IDictionary Convert(IReadOnlyDictionary source)
{
- return source.ToDictionary(exposedPort => $"{exposedPort.Key}/tcp", exposedPort => default(EmptyStruct));
+ return source?.ToDictionary(exposedPort => $"{exposedPort.Key}/tcp", exposedPort => default(EmptyStruct));
}
}
@@ -73,7 +73,7 @@ public ToPortBindings() : base("PortBindings")
public override IDictionary> Convert(IReadOnlyDictionary source)
{
- return source.ToDictionary(binding => $"{binding.Value}/tcp", binding => new List { new PortBinding { HostPort = binding.Key } } as IList);
+ return source?.ToDictionary(binding => $"{binding.Value}/tcp", binding => new List { new PortBinding { HostPort = binding.Key } } as IList);
}
}
@@ -85,7 +85,7 @@ public ToMounts() : base("Mounts")
public override IList Convert(IReadOnlyDictionary source)
{
- return source.Select(mount => new Mount { Source = Path.GetFullPath(mount.Key), Target = mount.Value, Type = "bind" }).ToList();
+ return source?.Select(mount => new Mount { Source = Path.GetFullPath(mount.Key), Target = mount.Value, Type = "bind" }).ToList();
}
}
}
diff --git a/src/DotNet.Testcontainers/Core/Models/DatabaseConfiguration.cs b/src/DotNet.Testcontainers/Core/Models/DatabaseConfiguration.cs
new file mode 100644
index 000000000..2b9b0f921
--- /dev/null
+++ b/src/DotNet.Testcontainers/Core/Models/DatabaseConfiguration.cs
@@ -0,0 +1,15 @@
+namespace DotNet.Testcontainers.Core.Models
+{
+ public class DatabaseConfiguration
+ {
+ public virtual string Hostname { get; set; } = "localhost";
+
+ public virtual string Port { get; set; }
+
+ public virtual string Database { get; set; }
+
+ public virtual string Username { get; set; }
+
+ public virtual string Password { get; set; }
+ }
+}
diff --git a/src/DotNet.Testcontainers/Core/Models/TestcontainersConfiguration.cs b/src/DotNet.Testcontainers/Core/Models/TestcontainersConfiguration.cs
index c5729ecf8..7013a8be9 100644
--- a/src/DotNet.Testcontainers/Core/Models/TestcontainersConfiguration.cs
+++ b/src/DotNet.Testcontainers/Core/Models/TestcontainersConfiguration.cs
@@ -5,7 +5,7 @@ namespace DotNet.Testcontainers.Core.Models
using System.Linq;
using DotNet.Testcontainers.Diagnostics;
- internal class TestcontainersConfiguration
+ public class TestcontainersConfiguration
{
public ContainerConfiguration Container { get; set; } = new ContainerConfiguration();
@@ -39,7 +39,7 @@ internal TestcontainersConfiguration Merge(TestcontainersConfiguration old)
this.Host.Mounts = Merge(this.Host.Mounts, old.Host.Mounts);
- this.CleanUp = old.CleanUp;
+ this.CleanUp = this.CleanUp && old.CleanUp;
this.OutputConsumer = Merge(this.OutputConsumer, old.OutputConsumer);
@@ -57,22 +57,22 @@ private static T Merge(T myself, T old)
private static IReadOnlyCollection Merge(IReadOnlyCollection myself, IReadOnlyCollection old)
where T : class
{
- if (myself == null)
+ if (myself == null || old == null)
{
- return old ?? new ReadOnlyCollection(new List());
+ return myself ?? old;
}
else
{
- return myself.Concat(old.Where(x => !myself.Contains(x))).ToList();
+ return myself.Concat(old).ToList();
}
}
private static IReadOnlyDictionary Merge(IReadOnlyDictionary myself, IReadOnlyDictionary old)
where T : class
{
- if (myself == null)
+ if (myself == null || old == null)
{
- return old ?? new ReadOnlyDictionary(new Dictionary());
+ return myself ?? old;
}
else
{
@@ -88,22 +88,22 @@ public class ContainerConfiguration
public string WorkingDirectory { get; set; }
- public IReadOnlyCollection Entrypoint { get; set; } = new List();
+ public IReadOnlyCollection Entrypoint { get; set; }
- public IReadOnlyCollection Command { get; set; } = new List();
+ public IReadOnlyCollection Command { get; set; }
- public IReadOnlyDictionary Environments { get; set; } = new Dictionary();
+ public IReadOnlyDictionary Environments { get; set; }
- public IReadOnlyDictionary Labels { get; set; } = new Dictionary();
+ public IReadOnlyDictionary Labels { get; set; }
- public IReadOnlyDictionary ExposedPorts { get; set; } = new Dictionary();
+ public IReadOnlyDictionary ExposedPorts { get; set; }
}
public class HostConfiguration
{
- public IReadOnlyDictionary PortBindings { get; set; } = new Dictionary();
+ public IReadOnlyDictionary PortBindings { get; set; }
- public IReadOnlyDictionary Mounts { get; set; } = new Dictionary();
+ public IReadOnlyDictionary Mounts { get; set; }
}
}
}