Home > database >  C# UnitTest void static method
C# UnitTest void static method

Time:11-25

I'm trying to make an unit test for a logger in an application. For example I need to test the method Logger.info("some message"), but this method is static and return void. Searching on Google I understand that I have to use Moq but am unable to implement that on the UnitTest class. The Logger constructor does not have an argument and in x.Debug I have an error that says that I can't access from instance reference. Is there a way to implement UnitTest without editing the production code?

[TestClass()]
public class LoggerTests
{
    [TestMethod()]
    public void DebugTest()
    { 
        var mock = new Mock<Logger>();
        mock.Setup(x => x.Debug(It.IsAny<string>());
        new Logger(mock.Object).AddLog("testing");
        mock.VerifyAll;
    }
}

Program.cs

private static void ConfigureLogger()
{
    Logger.AddLog(new NLogAppender());
    Logger.Level = TraceLevel.Verbose;
    Logger.Info("Configured Logger");
}

Logger.cs

public class Logger
{
    public static readonly List<IAppender> loggings = new List<IAppender>();

    public static void AddLog(IAppender appender)
    {
        loggings.Add(appender);
    }

    public static TraceLevel Level { get; set; }

    static Logger()
    {
        Level = TraceLevel.Verbose;
    }

    public static void Info(string message)
    {
        LogMessage(message);
    }
}

NlogAppender.cs

public class NLogAppender : IAppender
{
    public NLog.Logger logger;

    public NLogAppender()
    {
        logger = LogManager.GetLogger(nameof(NLogAppender));
    }

    public void AddLog(string str)
    {
    }
}

IAppender.cs

public interface IAppender
{
    void AddLog(string str);
}

CodePudding user response:

You can't mock a static class, and you shouldn't mock the class/system under test.

Add a mock appender to the logger:

// Arrange
var logString = "test-info"

var appenderMock = new Mock<IAppender>();

appenderMock.Setup(a => a.AddLog(logString));

Logger.AddLog(appenderMock.Object);

// Act
Logger.Info(logString);

// Assert
// TODO: exactly once
appenderMock.VerifyAll();

Note this static class may persist data between tests causing unexpected results, consult your test framework for configuring this.

Apart from that, you usually don't want to roll your own logging infrastructure, there's lots of things you can do wrong and why reinvent the wheel? Plenty of ILogger(<T>) implementations around.

  • Related