C# 如何为插值字符串设置模拟?
假设我有一个logger接口实现,上面有一个跟踪方法,比如: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
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
类似于$“..”
这样的表达式可以隐式转换为它,它接近于您所称的“模板引擎”(可能会看到我的新答案)。