使用模拟 TextWriter 测试控制台输出
Testing console output using a mock TextWriter
我正在尝试为输出到控制台的 class 编写单元测试。为了从此 class 捕获控制台输出,我决定创建一个模拟 TextWriter 对象并在测试 class 中将控制台输出重定向到它。
[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("foo") 它将起作用。
更奇怪的是,在调试测试时,来自 Logger class 的控制台似乎仍然被重定向到任何地方,因为单元测试除了 Assert 异常之外没有输出任何内容。
所以基本上我的问题是为什么模拟代码在从记录器 class 写入时没有得到 运行?
我想原因一定是你的ConsoleLogger
class(你没有显示谁的代码?)实际上调用了another overload或其他方法。
如果其他成员是 virtual
或 abstract
,Moq 将覆盖它。由于您没有为其他重载提供 Setup
,Moq 将提供带有 loose 模拟的 "empty" 实现,或者将使用 [=28= 抛出异常]strict 模拟。试试改成:
var mockWriter = new Mock<TextWriter>(MockBehavior.Strict);
看看这样的异常是否有助于发生。我的猜测:这是超载 WriteLine(object)
。使用严格模拟通常是个好主意。
但是,如果其他成员是非虚拟成员,则 Moq 没有机会修改其实现。然后将使用原始 class TextWriter
的实现。该实现可能会调用另一个 是 虚拟的成员,您可以 Setup
那个。
我正在尝试为输出到控制台的 class 编写单元测试。为了从此 class 捕获控制台输出,我决定创建一个模拟 TextWriter 对象并在测试 class 中将控制台输出重定向到它。
[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("foo") 它将起作用。
更奇怪的是,在调试测试时,来自 Logger class 的控制台似乎仍然被重定向到任何地方,因为单元测试除了 Assert 异常之外没有输出任何内容。
所以基本上我的问题是为什么模拟代码在从记录器 class 写入时没有得到 运行?
我想原因一定是你的ConsoleLogger
class(你没有显示谁的代码?)实际上调用了another overload或其他方法。
如果其他成员是 virtual
或 abstract
,Moq 将覆盖它。由于您没有为其他重载提供 Setup
,Moq 将提供带有 loose 模拟的 "empty" 实现,或者将使用 [=28= 抛出异常]strict 模拟。试试改成:
var mockWriter = new Mock<TextWriter>(MockBehavior.Strict);
看看这样的异常是否有助于发生。我的猜测:这是超载 WriteLine(object)
。使用严格模拟通常是个好主意。
但是,如果其他成员是非虚拟成员,则 Moq 没有机会修改其实现。然后将使用原始 class TextWriter
的实现。该实现可能会调用另一个 是 虚拟的成员,您可以 Setup
那个。