Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.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_Interface_Console_Inversion Of Control - Fatal编程技术网

C# 嘲弄';系统控制台';行为

C# 嘲弄';系统控制台';行为,c#,unit-testing,interface,console,inversion-of-control,C#,Unit Testing,Interface,Console,Inversion Of Control,有没有一种标准的方法可以让C#console应用程序单元通过接口而不是System.console编程来进行测试 例如,使用IConsole接口 你做过吗?你用了什么样的方法 您是否公开了应用程序何时需要写入标准输出的事件?昨晚我碰巧遇到了这个线程: @保罗想出了答案:菲利普·劳雷亚诺 上的使用示例指导您完成如何截获对Console.WriteLine方法的调用的示例,并(在本例中)执行一些其他操作。。。NET的AOP

有没有一种标准的方法可以让C#console应用程序单元通过接口而不是System.console编程来进行测试

例如,使用IConsole接口

你做过吗?你用了什么样的方法


您是否公开了应用程序何时需要写入标准输出的事件?

昨晚我碰巧遇到了这个线程:

@保罗想出了答案:菲利普·劳雷亚诺

上的使用示例指导您完成如何截获对Console.WriteLine方法的调用的示例,并(在本例中)执行一些其他操作。。。NET的AOP<很讨厌,伊姆霍

LinFu可能只是一张罚单,因为它在被截取的对象中不存在,因此您可以“在您的上下文中”截取并修改调用第三方供应商程序集的行为,但不可能影响该上下文之外被截取类的实际行为。。。因此,LinFu听起来是一个开始实施“控制台应用程序通用测试框架”的好地方

您甚至可以利用现有的单元测试框架之一。我正在寻找一个开源框架。我突然想起了努尼特。双关语

不管怎样,祝你好运,这是一个有趣的项目。保持联络,K


干杯。Keith.

我认为您使用接口的方法是可行的,而且我不认为我会利用事件。假设应用程序不接受除命令行参数以外的用户输入,我可能会使用类似的方式包装
Console.Write/Console.WriteLine

public interface IConsoleWriter
{
    void Write(string format, params object[] args);
    void WriteLine(string format, params object[] args);
}
为了进行测试,我要么创建一个
TestConsoleWriter
,将所有写操作存储到一个缓冲区中,然后根据缓冲区进行断言,要么创建一个mock并验证
Write
WriteLine
是否使用我期望的参数调用。如果您的应用程序将要对控制台进行大量的写入(比如+100MB左右的输出),那么出于性能原因,使用mock可能更可取,但否则我会说选择您认为更容易使用的方法

然而,这种方法确实有一些局限性。如果您使用的是无法修改的任何程序集,并且它们会写入控制台,那么您将看不到该输出,因为您无法强制这些类使用
IConsoleWriter
。另一个问题是
Write
WriteLine
方法有18个左右的重载,因此可能需要包装很多方法。为了绕过这些限制,您可能只想在测试时使用
控制台.SetOut
方法将控制台输出重定向到您自己的
TextWriter


就我个人而言,我想我会采取
出发
的方法。它只需在单元测试开始时添加一行(或者可能在
设置
方法中添加),您可以根据写入
TextWriter
的内容断言要在单元测试中更改console写入的流。然后你可以放进一个模拟流或者其他任何东西。检查Mark Seemann在测试控制台上的帖子:

我建议使用


主要是因为我更喜欢让您的设计决定您的接口和类,而不是您的测试。

如果您只使用一个线程,则此代码将起作用:

[TestClass]
public class MyTests
{
    private StringBuilder output;
    private StringWriter tempOutputWriter;
    private TextWriter originalOutputWriter;

    [TestInitialize]
    public void InitializeTest()
    {
        this.originalOutputWriter = Console.Out;
        this.tempOutputWriter = new StringWriter();
        Console.SetOut(tempOutputWriter);
        this.output = tempOutputWriter.GetStringBuilder();
    }

    [TestCleanup]
    public void CleanupTest()
    {
        Console.SetOut(originalOutputWriter);
        this.tempOutputWriter.Dispose();
    }

    [TestMethod]
    public void Test1()
    {
        Program.Main(new string[] { "1", "2", "3" });
        string output = this.output.ToString();
        ...
        this.output.Clear();
    }

    [TestMethod]
    public void Test2()
    {
        Program.Main(new string[] { "4", "5", "6" });
        string output = this.output.ToString();
        ...
        this.output.Clear();
    }
}

可能是重复的|微软正在开发一个开源软件包来处理这个问题(目前在nuget.org上以alpha的形式发布,但我希望这会很快改变)。其他人的回答都很好,但我支持这一个,因为它有效地将程序与具体的“控制台”实例隔离开来,这允许我编写一个纯单元测试。其他建议更适合于行为/集成测试。我没有想到
设置方法。整洁。使用setout/setin修改控制台行为的问题在于它如何与使用控制台本身的测试框架交互。console只有一点。setout方法-console是一个静态类。因此,当并行运行测试时,输出将混乱。就像@rsbarro提到的,Console.WriteLine有很多重写,但通常只有很少的重写被真正使用-因此,一旦需要,可以将方法定义逐个添加到IConsoleWriter中。@annakata xUnit非常聪明,因为它根本不使用控制台。可以在测试构造函数中注入
ITestOutputHelper
的实例,它就像控制台一样使用,同时不会干扰真正的控制台。感谢您的输入!我一直在研究的应用程序在这里:好主意,但这闻起来更像是集成测试。非常有趣的想法。如果我有更多的时间,我可以试试。这听起来是一个很好的方法,因为我正在替换方法。顺便说一句,我喜欢PEX,这也是一件很好的事情,至少可以玩一玩,以后要记住。