Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何为插值字符串设置模拟?_C#_Unit Testing_Moq_String Interpolation - Fatal编程技术网

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

C# 如何为插值字符串设置模拟?,c#,unit-testing,moq,string-interpolation,C#,Unit Testing,Moq,String Interpolation,假设我有一个logger接口实现,上面有一个跟踪方法,比如: public interface IMyLogger { void Trace(string message, params object[] parameters); } public class MyLogger : IMyLogger { public void Trace(string message, params object[] parameters) { // Writes t

假设我有一个logger接口实现,上面有一个跟踪方法,比如:

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);
}
[TestMethod]
公共无效DoSomeWork\u ShouldLogTrace()
{
var mockLogger=new Mock(MockBehavior.Strict);
Setup(l=>l.Trace(“x的值是5”,It.IsAny());
var testWorker=new MyWorker();
测试工人。DoSomeWork(5);
}
我的问题是:有没有一种方法可以将插入的字符串传递给跟踪设置,而不是字符串插入的结果

是否有一种方法可以将插入的字符串传递给跟踪设置,而不是字符串插入的结果

不,C#插值字符串不是模板引擎,而是编译时特性

这条线

Logger.Trace($"Value of x is {x}");
将调用带有格式化消息且无参数的
跟踪
方法


因此,可以使用经典占位符,也可以使用logger引擎,该引擎处理模板参数,例如。

您不能传递插值字符串,但可以验证是否使用预期值调用了
跟踪
方法

[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}"));
}
[TestMethod]
公共无效DoSomeWork\u ShouldLogWarning()
{
var mockLogger=new Mock(MockBehavior.Strict);
mockLogger.Setup(l=>l.Trace(It.IsAny(),It.IsAny());
var testWorker=newmyworker(mockLogger.Object);
const int expectedValue=5;
testWorker.DoSomeWork(期望值);
验证(x=>x.Trace($”x的值为{expectedValue}”);
}
在命名空间
系统中使用

也就是说,如果您可以有过载:

void Trace(FormattableString formattableMessage);
确保使用了这个,然后打电话如下:

Logger.Trace($"Value of x is {x}");
将生成一个“富”对象,您可以在其中检查
.Format
.GetArguments

解释是编译时表达式
$“..”
可隐式转换为不“插值”的特殊类型
FormattableString
立即,而是跟踪格式和每个参数。在实现中,
//将跟踪写入某个地方的日志文件
,在这个富对象上使用
.ToString()
,以执行实际的插值

然后,最小起订量设置类似于:

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

编辑:必须在模拟设置中使用索引为
{0}
,而不是
{x}

{0}
,我想不是。我不清楚你在问什么。你可以做
int x=5;
然后传递
$“x的值是{x}”
到模拟。也许参数化方法是一种方法。不幸的是,MSTest不太容易。xUnit有[理论]的概念。你也可以使用MSTest的数据源。但是,这并不像NUnit那么简单。请看,我建议你在(单元)方面自学测试,因为您要做的是复制实现细节。您应该测试行为和结果,而不是代码流。如果您将
DoSomeWork
方法更改为调用
Logger.Trace(string.Format(…)该怎么办
?它同样可以工作,但您的测试将失败。您从中得到了什么?验证将失败,因为您遗漏了params参数。这与mock上的设置一样,需要在发布答案之前测试代码。params是可选的。通常当忽略参数时,Moq会抱怨。
System.FORMATABLESTRING
类似于
$“..”
这样的表达式可以隐式转换为它,它接近于您所称的“模板引擎”(可能会看到我的新答案)。