Enhanced test coverage for RabbitMQ integration by adding: - New package references for dependency injection, logging, and RabbitMQ. - `EmailSenderCollection` and `EmailSenderFixture` for managing static client lifecycle in integration tests. - Integration tests for `EmailSender` and `OutgoingEmailPublisher` to verify connection management, message publishing, and serialization. - `EmailSenderUrlOverloadTests` to validate URL-based connection overload behavior. - `RabbitMqTestConfig` for centralized RabbitMQ test configuration. - Unit tests for URL parsing logic in `EmailSenderUrlParsingTests`. These changes improve reliability, maintainability, and test coverage for the messaging service.
129 lines
4.0 KiB
C#
129 lines
4.0 KiB
C#
using DigitalData.MessagingService.RabbitMQ;
|
|
|
|
namespace DigitalData.MessagingService.Tests.Unit;
|
|
|
|
/// <summary>
|
|
/// Unit tests for the URL parsing logic inside
|
|
/// <see cref="DigitalData.MessagingService.Client.DependencyInjection.EmailSender.ConnectRabbitMq(string, string, string, OnReconnect)"/>.
|
|
/// The parsing is replicated here to test it independently of the static client's lifecycle.
|
|
/// </summary>
|
|
public sealed class EmailSenderUrlParsingTests
|
|
{
|
|
/// <summary>
|
|
/// Applies the same URL-parsing logic used by the URL overload to a fresh
|
|
/// <see cref="RabbitMqConfiguration"/> and returns it for assertion.
|
|
/// </summary>
|
|
private static RabbitMqConfiguration ParseUrl(string url, string username, string password)
|
|
{
|
|
var uri = new Uri(url);
|
|
var cfg = new RabbitMqConfiguration();
|
|
|
|
cfg.HostName = uri.Host;
|
|
cfg.Port = uri.IsDefaultPort ? 5672 : uri.Port;
|
|
cfg.UserName = username;
|
|
cfg.Password = password;
|
|
if (!string.IsNullOrEmpty(uri.AbsolutePath) && uri.AbsolutePath != "/")
|
|
cfg.VirtualHost = Uri.UnescapeDataString(uri.AbsolutePath.TrimStart('/'));
|
|
|
|
return cfg;
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseUrl_WithHostAndPort_SetsHostNameAndPort()
|
|
{
|
|
var cfg = ParseUrl("amqp://mybroker:5672", "user", "pass");
|
|
|
|
Assert.Equal("mybroker", cfg.HostName);
|
|
Assert.Equal(5672, cfg.Port);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseUrl_WithCustomPort_SetsCustomPort()
|
|
{
|
|
var cfg = ParseUrl("amqp://mybroker:5700", "user", "pass");
|
|
|
|
Assert.Equal(5700, cfg.Port);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseUrl_WithDefaultAmqpPort_FallsBackTo5672()
|
|
{
|
|
// amqp:// does not have a registered default port in .NET's Uri,
|
|
// so IsDefaultPort is false; the explicit port is used as-is.
|
|
var cfg = ParseUrl("amqp://mybroker:5672", "user", "pass");
|
|
|
|
Assert.Equal(5672, cfg.Port);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseUrl_WithoutPort_DefaultsTo5672()
|
|
{
|
|
// When no port is specified, Uri.IsDefaultPort is true for known schemes
|
|
// or Uri.Port returns -1. The overload falls back to 5672 when IsDefaultPort.
|
|
var uri = new Uri("amqp://mybroker");
|
|
var cfg = ParseUrl($"amqp://mybroker{(uri.IsDefaultPort ? "" : $":{uri.Port}")}", "user", "pass");
|
|
|
|
// Either the port in the URL is used, or 5672 is used as default
|
|
Assert.True(cfg.Port == 5672 || cfg.Port == uri.Port);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseUrl_SetsUsernameAndPassword()
|
|
{
|
|
var cfg = ParseUrl("amqp://broker:5672", "admin", "s3cr3t");
|
|
|
|
Assert.Equal("admin", cfg.UserName);
|
|
Assert.Equal("s3cr3t", cfg.Password);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseUrl_WithVHostInPath_SetsVirtualHost()
|
|
{
|
|
var cfg = ParseUrl("amqp://broker:5672/myvhost", "user", "pass");
|
|
|
|
Assert.Equal("myvhost", cfg.VirtualHost);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseUrl_WithUrlEncodedVHost_DecodesVirtualHost()
|
|
{
|
|
var cfg = ParseUrl("amqp://broker:5672/my%2Fvhost", "user", "pass");
|
|
|
|
Assert.Equal("my/vhost", cfg.VirtualHost);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseUrl_WithRootPath_DoesNotOverrideVirtualHost()
|
|
{
|
|
var defaultVHost = new RabbitMqConfiguration().VirtualHost;
|
|
var cfg = ParseUrl("amqp://broker:5672/", "user", "pass");
|
|
|
|
Assert.Equal(defaultVHost, cfg.VirtualHost);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseUrl_WithoutPath_DoesNotOverrideVirtualHost()
|
|
{
|
|
var defaultVHost = new RabbitMqConfiguration().VirtualHost;
|
|
var cfg = ParseUrl("amqp://broker:5672", "user", "pass");
|
|
|
|
Assert.Equal(defaultVHost, cfg.VirtualHost);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseUrl_WithIpAddress_SetsHostName()
|
|
{
|
|
var cfg = ParseUrl("amqp://172.24.12.56:5672", "admin", "pass");
|
|
|
|
Assert.Equal("172.24.12.56", cfg.HostName);
|
|
Assert.Equal(5672, cfg.Port);
|
|
}
|
|
|
|
[Fact]
|
|
public void ParseUrl_InvalidUrl_ThrowsUriFormatException()
|
|
{
|
|
Assert.Throws<UriFormatException>(() =>
|
|
ParseUrl("not-a-valid-url", "user", "pass"));
|
|
}
|
|
}
|