C
C#•12mo ago
LazyGuard

How to test this code?

I am trying to refactor some code in a background service that looks like this:
public class MyBackgroundService : BackgroundService {
public MyBackgroundService(IKafkaConsumer consumer, IOptionMonithor<WorkerConfig> config, NotificationSender sender)
{
_consumer = consumer;
_config = config;
_sender = sender;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while(!stoppingToken.IsCancellationRequested)
{
await ConsumeKafkaAndSendNotificationAsync();
await Task.Delay(TimeSpan.FromMilliseconds(_config.CurrentValue.Delay), stoppingToken);
}
}

private async Task ConsumeKafkaAndSendNotificationAsyncc()
{
var timer = new StopWatch();
timer.Start();
Message? message;
do
{
message = _consumer.ConsumeMessage();
// .....
// do some work here on the message
// .....
await _sender.SendNotificationAsync(message);
} while (
message != null && timer.Elapsed < TimeSpan.FromMilliseconds(_config.CurrentValue.Delay)
)
}
}
public class MyBackgroundService : BackgroundService {
public MyBackgroundService(IKafkaConsumer consumer, IOptionMonithor<WorkerConfig> config, NotificationSender sender)
{
_consumer = consumer;
_config = config;
_sender = sender;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while(!stoppingToken.IsCancellationRequested)
{
await ConsumeKafkaAndSendNotificationAsync();
await Task.Delay(TimeSpan.FromMilliseconds(_config.CurrentValue.Delay), stoppingToken);
}
}

private async Task ConsumeKafkaAndSendNotificationAsyncc()
{
var timer = new StopWatch();
timer.Start();
Message? message;
do
{
message = _consumer.ConsumeMessage();
// .....
// do some work here on the message
// .....
await _sender.SendNotificationAsync(message);
} while (
message != null && timer.Elapsed < TimeSpan.FromMilliseconds(_config.CurrentValue.Delay)
)
}
}
Complex work should usually be kept somewhere else outside of the loop of the backgroundService. However, things get hairy enough that some tests will help.
2 Replies
LazyGuard
LazyGuardOP•12mo ago
To test the code, II mocked the consumer and i have a lot of tests like this
[Fact]
public async Task Should_Assert_That_Some_Work_Is_Done()
{
// Arrange
var message = new Mesagge(...);
MockedConsumer.ConsumeMessage().ReturnsForAnyArgs(x =>message, x =>null));

Notification? sentNotification = null;
MockedSender.SendNotificationAsync(Arg.Do<Notification>(x => sentNotification = x)).Returns(Task.CompletedTask);

// Act
Task.Delay(Configuration.Delay + 100).Wait();

//Assert
// Some assertions on the work being done
Assert.NotNull(sentNotification?.Message?.Price);

}
[Fact]
public async Task Should_Assert_That_Some_Work_Is_Done()
{
// Arrange
var message = new Mesagge(...);
MockedConsumer.ConsumeMessage().ReturnsForAnyArgs(x =>message, x =>null));

Notification? sentNotification = null;
MockedSender.SendNotificationAsync(Arg.Do<Notification>(x => sentNotification = x)).Returns(Task.CompletedTask);

// Act
Task.Delay(Configuration.Delay + 100).Wait();

//Assert
// Some assertions on the work being done
Assert.NotNull(sentNotification?.Message?.Price);

}
When I launch tests, the majority fail and I am trying to wrap my head around and understand why. When Launching tests individually, they all pass ! Observations: 1. Some tests fail with a null value when a non null value is expected 2. Some tests fail with a value that is not null but different from the expected. Any help ? 🤔
phaseshift
phaseshift•12mo ago
Is MockedSender static or part of a fixture? If you want to wait until a message is received in a mock then use some form of barrier like ManualResetEvent (instead of doing an arbitrary wait, which btw is not the 'Act' of the test)
Want results from more Discord servers?
Add your server