-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial tests for Chats service and check how Testcontainers pack…
…age works
- Loading branch information
1 parent
c73012d
commit 7652b09
Showing
3 changed files
with
217 additions
and
0 deletions.
There are no files selected for viewing
29 changes: 29 additions & 0 deletions
29
source/CecoChat.Chats.Testing/CecoChat.Chats.Testing.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="coverlet.msbuild" Version="6.0.2" /> | ||
<PackageReference Include="FluentAssertions" Version="6.12.0" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" /> | ||
<PackageReference Include="NUnit" Version="4.1.0" /> | ||
<PackageReference Include="NUnit.Analyzers" Version="4.2.0" /> | ||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" /> | ||
<PackageReference Include="Serilog" Version="3.1.1" /> | ||
<PackageReference Include="Testcontainers" Version="3.8.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\CecoChat.Chats.Client\CecoChat.Chats.Client.csproj" /> | ||
<ProjectReference Include="..\CecoChat.Chats.Service\CecoChat.Chats.Service.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Content Include="..\certificates\services.pfx" Link="services.pfx"> | ||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||
</Content> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
using Cassandra; | ||
using Common; | ||
using Common.Cassandra; | ||
using DotNet.Testcontainers.Builders; | ||
using DotNet.Testcontainers.Configurations; | ||
using DotNet.Testcontainers.Containers; | ||
using DotNet.Testcontainers.Networks; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Logging.Abstractions; | ||
using Microsoft.Extensions.Options; | ||
using NUnit.Framework; | ||
|
||
namespace CecoChat.Chats.Testing; | ||
|
||
public class TestContainers | ||
{ | ||
private INetwork _network; | ||
private IContainer _cassandra; | ||
|
||
[OneTimeSetUp] | ||
public async Task Setup() | ||
{ | ||
_network = new NetworkBuilder() | ||
.WithName("cecochat") | ||
.Build(); | ||
|
||
const int port = 9042; | ||
const string localDc = "Europe"; | ||
|
||
_cassandra = new ContainerBuilder() | ||
.WithImage("cassandra:4.1.3") | ||
.WithName("cecochat-test-cassandra0") | ||
.WithHostname("cassandra0") | ||
.WithNetwork(_network) | ||
.WithPortBinding(hostPort: port, containerPort: port) | ||
.WithEnvironment(new Dictionary<string, string> | ||
{ | ||
{ "CASSANDRA_SEEDS", "cassandra0" }, | ||
{ "CASSANDRA_CLUSTER_NAME", "cecochat" }, | ||
{ "CASSANDRA_DC", localDc }, | ||
{ "CASSANDRA_RACK", "Rack0" }, | ||
{ "CASSANDRA_ENDPOINT_SNITCH", "GossipingPropertyFileSnitch" }, | ||
{ "CASSANDRA_NUM_TOKENS", "128" }, | ||
{ "HEAP_NEWSIZE", "128M" }, | ||
{ "MAX_HEAP_SIZE", "512M" } | ||
}) | ||
.WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged("Starting listening for CQL clients on /0.0.0.0:9042")) | ||
.WithWaitStrategy(Wait.ForUnixContainer().UntilCassandraQueryExecuted(port, localDc)) | ||
.WithLogger(new NUnitProgressLogger()) | ||
.Build(); | ||
|
||
await _cassandra.StartAsync(); | ||
} | ||
|
||
[OneTimeTearDown] | ||
public async Task TearDown() | ||
{ | ||
await _cassandra.DisposeAsync(); | ||
await _network.DisposeAsync(); | ||
} | ||
|
||
[Test] | ||
public void Test1() | ||
{ | ||
CassandraOptions options = new() | ||
{ | ||
ContactPoints = [$"{_cassandra.Hostname}:9042"], | ||
LocalDc = "Europe", | ||
SocketConnectTimeout = TimeSpan.FromSeconds(5), | ||
ExponentialReconnectPolicy = true, | ||
ExponentialReconnectPolicyBaseDelay = TimeSpan.FromMilliseconds(500), | ||
ExponentialReconnectPolicyMaxDelay = TimeSpan.FromSeconds(5) | ||
}; | ||
|
||
using (CassandraDbContext db = new(new NullLogger<CassandraDbContext>(), new OptionsWrapper<CassandraOptions>(options))) | ||
{ | ||
TestContext.Progress.WriteLine("Exists keyspace? {0}", db.ExistsKeyspace("unknown")); | ||
} | ||
} | ||
} | ||
|
||
public class NUnitProgressLogger : ILogger | ||
{ | ||
#pragma warning disable IDE0060 | ||
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null; | ||
#pragma warning restore IDE0060 | ||
|
||
#pragma warning disable IDE0060 | ||
public bool IsEnabled(LogLevel logLevel) => true; | ||
#pragma warning restore IDE0060 | ||
|
||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) | ||
{ | ||
string message = formatter.Invoke(state, exception); | ||
string level; | ||
switch (logLevel) | ||
{ | ||
case LogLevel.Trace: | ||
level = "VRB"; | ||
break; | ||
case LogLevel.Debug: | ||
level = "DBG"; | ||
break; | ||
case LogLevel.Information: | ||
level = "INF"; | ||
break; | ||
case LogLevel.Warning: | ||
level = "WRN"; | ||
break; | ||
case LogLevel.Error: | ||
level = "ERR"; | ||
break; | ||
case LogLevel.Critical: | ||
level = "CRI"; | ||
break; | ||
default: | ||
throw new EnumValueNotSupportedException(logLevel); | ||
} | ||
TestContext.Progress.WriteLine("[{0} Custom] {1}", level, message); | ||
} | ||
} | ||
|
||
public static class WaitForContainerOsExtensions | ||
{ | ||
public static IWaitForContainerOS UntilCassandraQueryExecuted(this IWaitForContainerOS waitFor, int port, string localDc) | ||
{ | ||
return waitFor.AddCustomWaitStrategy(new CassandraQueryExecutedWaitStrategy(port, localDc)); | ||
} | ||
} | ||
|
||
public class CassandraQueryExecutedWaitStrategy : IWaitUntil | ||
{ | ||
private readonly int _port; | ||
private readonly string _localDc; | ||
private bool _showedError; | ||
|
||
public CassandraQueryExecutedWaitStrategy(int port, string localDc) | ||
{ | ||
_port = port; | ||
_localDc = localDc; | ||
} | ||
|
||
public Task<bool> UntilAsync(IContainer container) | ||
{ | ||
CassandraOptions options = new() | ||
{ | ||
ContactPoints = [$"{container.Hostname}:{_port}"], | ||
LocalDc = _localDc, | ||
SocketConnectTimeout = TimeSpan.FromSeconds(5), | ||
ExponentialReconnectPolicy = true, | ||
ExponentialReconnectPolicyBaseDelay = TimeSpan.FromMilliseconds(500), | ||
ExponentialReconnectPolicyMaxDelay = TimeSpan.FromSeconds(5) | ||
}; | ||
|
||
CassandraDbContext? db = null; | ||
|
||
try | ||
{ | ||
db = new(new NullLogger<CassandraDbContext>(), new OptionsWrapper<CassandraOptions>(options)); | ||
// we simply want to make sure that there is connection to the cassandra cluster | ||
// we don't care if this keyspace actually exists | ||
db.ExistsKeyspace("non-existing"); | ||
|
||
return Task.FromResult(true); | ||
} | ||
catch (NoHostAvailableException noHostAvailableException) | ||
{ | ||
if (!_showedError) | ||
{ | ||
container.Logger.LogError(noHostAvailableException, "No connection to Cassandra at {Host}:{Port} (showing this error only the first time)", container.Hostname, _port); | ||
_showedError = true; | ||
} | ||
|
||
return Task.FromResult(false); | ||
} | ||
finally | ||
{ | ||
db?.Dispose(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters