Search code examples
c#unit-testingmoqstring-interpolation

How to setup a mock for an interpolated string?


Let's say I have a logger interface implementation that has a Trace method on it, like such:

public interface IMyLogger
{
    void Trace(string message, params object[] parameters);
}

public class MyLogger : IMyLogger
{
    public void Trace(string message, params object[] parameters)
    {
        // Writes the trace to a log file somewhere
    }
}

And a method call using this logger call with an interpolated string like so:

public class MyWorker
{
    private IMyLogger Logger { get; set; }

    public MyWorker(IMyLogger logger)
    {
        Logger = logger;
    }

    public void DoSomeWork(int x)
    {
        Logger.Trace($"Value of x is {x}");
    }
}

I'm writing a unit test for the DoSomeWork method. This is what I have right now, and the test passes:

[TestMethod]
public void DoSomeWork_ShouldLogTrace()
{
    var mockLogger = new Mock<IMyLogger>(MockBehavior.Strict);
    mockLogger.Setup(l => l.Trace("Value of x is 5", It.IsAny<object[]>());

    var testWorker = new MyWorker();
    testWorker.DoSomeWork(5);
}

My question is: is there a way I can pass the interpolated string to the Trace setup instead of the result of the string interpolation?


Solution

  • is there a way I can pass the interpolated string to the Trace setup instead of the result of the string interpolation?

    No. C# interpolated string is not a templating engine but a compile-time feature.

    This line

    Logger.Trace($"Value of x is {x}");
    

    will call the Trace method with the formatted message and no parameters.

    So use either the classic placeholders or use a logger engine, which processes template parameters such as Serilog.