我正在尝试为输出到控制台的类编写单元测试。为了从这个类中捕获控制台输出,我决定创建一个模拟TextWriter对象,并在测试类中将控制台输出重定向到它。
[TestMethod]
public void TestMethod()
{
var outLines = new List<string>();
var mockWriter = new Mock<TextWriter>();
mockWriter.Setup(writer => writer.WriteLine(It.IsAny<string>()))
.Callback<string>(s => outLines.Add(s));
Console.SetOut(mockWriter.Object);
// ConsoleLogger is the class being tested
// It will essentially just print its parameter to the console.
var logger = new ConsoleLogger();
logger.Error("foo");
// Uncommenting this will cause the test to pass
// Console.WriteLine("foo");
Assert.AreEqual(1, outLines.Count);
Assert.AreEqual("foo", outLines[0]);
}
此代码不起作用。但是,如果我在测试中执行Console.WriteLine(&#34; foo&#34;),它将起作用。
更奇怪的是,在调试测试时,Logger类中的控制台仍然被重定向,因为单元测试不会从Assert异常中输出任何内容。
所以基本上我的问题是为什么在从logger类写入时不能运行模拟代码?
答案 0 :(得分:1)
我认为原因必须是你的ConsoleLogger
类(你的代码没有显示?)实际调用another overload或其他方法。
如果该其他成员是virtual
或abstract
,则Moq会覆盖它。由于您没有为其他重载提供Setup
,因此Moq将使用松散模拟提供“空”实现,或者使用严格模拟引发异常。尝试改为:
var mockWriter = new Mock<TextWriter>(MockBehavior.Strict);
查看是否有助于发生此类异常。我猜:这是重载WriteLine(object)
。使用严格的模拟通常是个好主意。
但是,如果该其他成员是非虚拟成员,则Moq无法修改其实现。然后将使用原始类TextWriter
的实现。该实现可能会调用 虚拟的其他成员,您可以Setup
。