Nixit
Nixit

Reputation: 21

Unit testing custom Serilog sink

I am working on a custom Serilog sink, inheriting from PeriodicBatchingSink and calling my web service to write data into db, using pattern similar to Serilog.Sinks.Seq. Using this code as example https://github.com/serilog/serilog-sinks-seq/blob/dev/src/Serilog.Sinks.Seq/Sinks/Seq/SeqSink.cs I am overriding EmitBatchAsync and from there calling my web service.

public AppSink(string serverUrl, int batchSizeLimit,
                            TimeSpan period, long? eventBodyLimitBytes))
            : base(batchSizeLimit, period)
    {
        ...
    }

    protected override async Task EmitBatchAsync(IEnumerable<LogEvent> events)
    {
        ...
        var result = await _httpClient.PostAsJsonAsync(Uri, logEntriesList);
    }

Trying to write some xunit tests to test actual LogEvent roundtrip, but can't figure how to wait for the Task to complete, using async and await doesn't work - logger still processes all log events asynchronously, and the test completes without waiting. Neither Log.Debug nor overridden EmitBatchAsync return anything.

This is just a sample of what I'm trying to test:

[Fact]
    public void Test_LogMessages()
    {
        InitAppSink();

        Log.Logger = new LoggerConfiguration().ReadFrom.AppSettings()
            .WriteTo.Sink(testSink)
            .MinimumLevel.ControlledBy(_levelSwitch)
            .CreateLogger();

        Log.Information("Information Test Log Entry");
        Log.Debug("Debug Test Log Entry");
    }

Sample tests on the Serilog page are not much help, even comments there say "// Some very, very approximate tests here :)" , or maybe I'm missing something. Or maybe it's the fact that I'm new to both Serilog and async testing.

What would be the best way to unit test Log.Debug("msg") in this case?

Upvotes: 2

Views: 4743

Answers (1)

Nicholas Blumhardt
Nicholas Blumhardt

Reputation: 31857

One option that may work for you is to dispose the sink and/or logger to flush any pending batches:

[Fact]
public void Test_LogMessages()
{
    InitAppSink();

    var logger = new LoggerConfiguration().ReadFrom.AppSettings()
        .WriteTo.Sink(testSink)
        .MinimumLevel.ControlledBy(_levelSwitch)
        .CreateLogger();

    logger.Information("Information Test Log Entry");
    logger.Debug("Debug Test Log Entry");
    ((IDisposable)logger).Dispose();
}

The sink directly implements IDisposable, so:

    testSink.Dispose();

...would probably achieve this too.

Upvotes: 2

Related Questions