如何为插值字符串设置模拟?

时间:2018-02-16 15:37:58

标签: c# unit-testing moq string-interpolation

假设我有一个记录器接口实现,其上有一个Trace方法,如下所示:

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
    }
}

使用此记录器调用的方法调用,使用内插字符串,如下所示:

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}");
    }
}

我正在为DoSomeWork方法编写单元测试。这就是我现在所拥有的,测试通过了:

[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);
}

我的问题是:有没有办法可以将插值字符串传递给Trace设置而不是字符串插值的结果?

3 个答案:

答案 0 :(得分:3)

  

有没有办法可以将插值字符串传递给Trace设置而不是字符串插值的结果?

没有。 C#interpolated string不是模板引擎,而是编译时功能。

这一行

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

将使用格式化的消息调用Trace方法,而不使用参数。

因此,请使用经典占位符或使用记录器引擎,该引擎处理模板参数,例如Serilog

答案 1 :(得分:1)

您无法传递插值字符串,但您可以验证是否使用您期望的值调用了Trace方法。

[TestMethod]
public void DoSomeWork_ShouldLogWarning()
{
    var mockLogger = new Mock<IMyLogger>(MockBehavior.Strict);
    mockLogger.Setup(l => l.Trace(It.IsAny<string>(), It.IsAny<object[]>()));

    var testWorker = new MyWorker(mockLogger.Object);

    const int expectedValue = 5;

    testWorker.DoSomeWork(expectedValue);

    mockLogger.Verify(x => x.Trace($"Value of x is {expectedValue}"));
}

答案 2 :(得分:0)

在名称空间System中使用FormattableString type

也就是说,如果你有一个过载:

void Trace(FormattableString formattableMessage);

并确保使用它,然后调用如下:

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

将生成一个“富”对象,您可以在其中检查.Format.GetArguments等。

解释是编译时表达式$" ... " 可隐式转换到特殊类型FormattableString,它不会立即“插入”,而是跟踪格式和每个参数。在实现// Writes the trace to a log file somewhere中,对此富对象使用.ToString()以执行实际插值。

然后Moq设置类似于:

// using nice Strict mock
mockLogger.Setup(l => l.Trace(It.Is(
  (FormattableString x) => x.Format == "Value of x is {0}"
  )));

已修改:必须在模拟设置中使用带有{0}索引的0,而不是{x}