I need to test a method of type void
, it just inserts a message on my LOG variable using a LOG framework (Serilog).
See the implementation example:
public class MyClass
{
public MyClass(ILogger<IProcess> logger)
{
this.logger = logger;
}
private readonly ILogger logger;
//...Anothers methods...
public void LogInit(Guid processId, string folder, string[] args)
{
var myObject = new
{
ProcessId = processId,
Folder = folder,
Arguments = args
};
this.logger.LogWarning("{@myObject}", myObject);
}
}
In this scenario, we would need to create a test for the LogInit (...)
Does this method really need to be tested? Or rather, does it make sense for it to exist?
I was reading something about:
"If your method has no side effects, and doesn’t return anything, then it’s not doing anything."
In this case, the method was only created "separately" to maintain the organization of the code and separate the responsibilities of the class a bit more.
That makes sense?
EDIT: @PeterBons
We do not have access to the messages registered in the Interface (logger
), like: this.logger.GiveMeWarningLogs()
...
Mockito provides following methods that can be used to mock void methods. doAnswer() : We can use this to perform some operations when a mocked object method is called that is returning void. doThrow() : We can use doThrow() when we want to stub a void method that throws exception.
To mock an ILogger<T> object, we can use Moq library to instantiate a new Mock<ILogger<T>>() object. Make sure you have installed the latest Moq package (v4. 15.1 as of Nov. 16, 2020, which contains an update to support “nested” type matchers).
You have to mock your logger and check whether LogWarning method was called. You can use Moq for this. Also if you want to test LogInit you need to make this public or internal with defining [InternalVisibleTo('someTestProjName')]
Test method will looks like this (xUnit):
public void ShouldCallLogWarning()
{
var loggerMock = new Mock<ILogger>();
loggerMock.Setup(_ => _.LogWarning(It.IsAny<string>(), It.IsAny<object>(), null);
var myClass = new MyClass(loggerMock.Object);
//
myClass.LogInit(Guid.NewGuid(), "folderPath", null)
//
_loggerMock.Verify(_ => _.LogWarning(It.IsAny<string>(), It.IsAny<string>(), null), Times.Once());
}
If you're using Serilog, you can use the Test Correlator Sink to see what log events a method call produced.
[TestMethod]
public void A_test()
{
var myClass = new MyClass(new LoggerConfiguration().WriteTo.TestCorrelator().CreateLogger());
using (TestCorrelator.CreateContext())
{
myClass.LogInit();
TestCorrelator.GetLogEventsFromCurrentContext()
.Should().ContainSingle()
.Which.MessageTemplate.Text
.Should().Be("{@myObject}");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With