Samples
Fixture
using FluentTesting.Common;
using FluentTesting.Common.Extensions;
using FluentTesting.Common.Interfaces;
using FluentTesting.RabbitMq;
using FluentTesting.RabbitMq.Options;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Samples.Worker.RabbitMq.ConsumptionHandlingServices;
namespace Samples.Worker.RabbitMq.Tests.Shared;
/// <summary>
/// Example of test fixture with custom options
/// </summary>
public class TestFixture : ITestFixture
{
public IApplicationFactory ApplicationFactory { get; }
public readonly Mock<IConsumptionHandler> ConsumptionHandlerMock = new();
public TestFixture()
{
ApplicationFactory = new ApplicationFactoryBuilder<Program>()
.RegisterServices((services, configuration) =>
{
services.AddSingleton(ConsumptionHandlerMock.Object);
})
.UseRabbitMq((configuration, rabbitSettings) =>
{
configuration.AddObject("RabbitConnectionOptions", new RabbitConnectionOptions()
{
HostName = rabbitSettings.Host,
Password = rabbitSettings.Password,
UserName = rabbitSettings.UserName,
});
}, opts =>
{
opts.PublisherBindings = [new Exchange() {
ExchangeName = "test",
RoutingKeys = ["testRoutingKey"]
}];
opts.ConsumerBindings = [
new Exchange()
{
ExchangeName = "consumptionTest",
RoutingKeys = ["RabbitMessage"],
QueueName = "ConsumptionTestRabbitMessageQueue"
}
];
opts.DefaultQueueName = "testQueue";
})
.Build();
}
}
Publishing on app run in worker service
using Microsoft.Extensions.Options;
using RabbitMQ.Client;
using System.Text;
namespace Samples.Worker.RabbitMq
{
public class RabbitPublishingWorker(IOptions<RabbitConnectionOptions> opts) : BackgroundService
{
private readonly RabbitConnectionOptions rabbitOpts = opts.Value;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var factory = new ConnectionFactory
{
HostName = rabbitOpts.HostName,
UserName = rabbitOpts.UserName,
Password = rabbitOpts.Password,
};
using var connection = await factory.CreateConnectionAsync(stoppingToken);
using var channel = await connection.CreateChannelAsync(null, stoppingToken);
byte[] messageBodyBytes = Encoding.UTF8.GetBytes("Hello, world!");
await channel.BasicPublishAsync("test", "testRoutingKey", true, new BasicProperties(), messageBodyBytes, stoppingToken);
await channel.CloseAsync(cancellationToken: stoppingToken);
await connection.CloseAsync(cancellationToken: stoppingToken);
}
}
}
Test - consumming message from rabbit to assert that it was published sucessfully
using FluentAssertions;
using FluentTesting.Common.Extensions;
using FluentTesting.RabbitMq.Extensions;
using Samples.Worker.RabbitMq.Tests.Shared;
namespace Samples.Worker.RabbitMq.Tests
{
[Collection("RabbitMqFixture")]
public class RabbitPublisherTests(TestFixture fixture)
{
[Fact]
public async Task PublishFromApp_ShouldWork()
{
var cts = fixture.GetCtsWithTimeoutInSeconds();
await Task.Delay(1000);
var consumed = await fixture.ApplicationFactory.ConsumeRabbitMqMessage(cts.Token);
consumed.Should().NotBeNull();
consumed?.Payload.Should().Be("Hello, world!");
}
}
}
Test - publishing message to RabbitMQ which is sucessfully managed by application
using FluentAssertions;
using FluentTesting.Common.Extensions;
using FluentTesting.RabbitMq.Extensions;
using Moq;
using Samples.Worker.RabbitMq.ConsumptionHandlingServices;
using Samples.Worker.RabbitMq.Contracts;
using Samples.Worker.RabbitMq.Tests.Shared;
namespace Samples.Worker.RabbitMq.Tests
{
[Collection("RabbitMqFixture")]
public class RabbitConsumerTests(TestFixture fixture)
{
[Fact]
public async Task ObtainingMessages_Should_Work()
{
var contract = new RabbitMessage()
{
BirthDate = DateTime.Now,
Email = "coconut@coco.com",
SurName = "Testschenko",
Name = "Testicss"
};
var cts = fixture.GetCtsWithTimeoutInSeconds(60);
// pseudo unmocking process to create callback to stop waiting for consumption, cause message has been consumed
fixture.UnmockAndWait<IConsumptionHandler, bool, RabbitMessage, CancellationToken>(
fixture.ConsumptionHandlerMock,
src => src.HandleMessageAsync(It.IsAny<RabbitMessage>(), It.IsAny<CancellationToken>()),
cts);
await fixture.ApplicationFactory.PublishJsonToRabbitAndWaitForConsumption("consumptionTest", "RabbitMessage", contract, cts);
// This should be asserted against db or handler should create new notification etc
// This static object is just here for test purposes where i don't want to include db or smth
// but it is filled in handler where message is handled
StaticRabbitHandlerState.RabbitMessage.BirthDate.Should().Be(contract.BirthDate);
StaticRabbitHandlerState.RabbitMessage.Email.Should().Be(contract.Email);
StaticRabbitHandlerState.RabbitMessage.SurName.Should().Be(contract.SurName);
StaticRabbitHandlerState.RabbitMessage.Name.Should().Be(contract.Name);
}
}
}