使用模拟TextWriter

时间:2015-07-24 16:33:14

标签: c# unit-testing mocking moq

我正在尝试为输出到控制台的类编写单元测试。为了从这个类中捕获控制台输出,我决定创建一个模拟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类写入时不能运行模拟代码?

1 个答案:

答案 0 :(得分:1)

我认为原因必须是你的ConsoleLogger类(你的代码没有显示?)实际调用another overload或其他方法。

如果该其他成员是virtualabstract,则Moq会覆盖它。由于您没有为其他重载提供Setup,因此Moq将使用松散模拟提供“空”实现,或者使用严格模拟引发异常。尝试改为:

var mockWriter = new Mock<TextWriter>(MockBehavior.Strict);

查看是否有助于发生此类异常。我猜:这是重载WriteLine(object)。使用严格的模拟通常是个好主意。

但是,如果该其他成员是非虚拟成员,则Moq无法修改其实现。然后将使用原始类TextWriter的实现。该实现可能会调用 虚拟的其他成员,您可以Setup