Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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#_Multithreading_Unit Testing_Task Parallel Library - Fatal编程技术网

C# 在单元测试中,如何控制(暂停、恢复)被测对象的内部后台任务

C# 在单元测试中,如何控制(暂停、恢复)被测对象的内部后台任务,c#,multithreading,unit-testing,task-parallel-library,C#,Multithreading,Unit Testing,Task Parallel Library,为了让一般问题更生动,我有以下简单的类将结果写入文件: class ResultWriter { private BlockingCollection<string> buffer; public ResultWriter(TextWriter writer, int bufferSize) { buffer = new BlockingCollection<string>(bufferSize); Task.Fa

为了让一般问题更生动,我有以下简单的类将结果写入文件:

class ResultWriter
{
    private BlockingCollection<string> buffer;

    public ResultWriter(TextWriter writer, int bufferSize)
    {
        buffer = new BlockingCollection<string>(bufferSize);
        Task.Factory.StartNew(() =>
            {
                using (writer)
                {
                    foreach (string s in buffer.GetConsumingEnumerable())
                    {
                        writer.WriteLine(s);
                    }
                }
            });
    }

    public long GetBufferConsumption()
    {
        return buffer.Count;
    }
}
问题很明显,在添加一到两个项之后,内部后台任务(我们称之为consumer)开始消耗它们,这会产生一种随机的缓冲区计数

到目前为止,我考虑了以下选择:

  • 未测试此方法-不,显然我不想这样做:)
  • 将使用者提取为一个单独的类,然后将其模拟传递给我的测试-我不喜欢这种想法,因为使用者在概念上是ResultWriter类的内部成员。。。我不想仅仅为了测试而对代码进行不自然的更改
  • 使用一些TextWriter模拟,而不是StringWriter,这将阻止我想要的消费-这也不是完美的,因为我第一次能够阻止消费线程是line:
    writer.WriteLine这已经在以下行之后:
    foreach(buffer.getconsumineGenumerable()中的字符串s)
    ,它实际上已经使用了缓冲区中的第一个项。现在有一个测试增加了5个项目,然后仅仅因为上面的原因就期望有4个项目,这似乎远远不够优雅
  • 模拟ResultWriter类并修改构造函数以延迟任务启动-我不相信模拟测试对象。如果可能的话,我想避免这种方法
  • 使
    buffer.Count
    属性以某种方式可访问以进行测试,并将其与
    GetBufferConsumption()
    的结果进行比较-除了需要摆弄属性的可见性之外(我不喜欢),我仍然需要停止消费者,以确保在
    GetBufferConsumption()之间没有消耗任何内容
    调用并检查
    缓冲区。计数

  • 这是一个与您的问题无关的小建议,但您应该使用Assert.AreEqual进行该类型的测试,而不是Assert.IsTrue。当IsTrue失败时,你只知道它不是真的,而如果你期望5而没有得到5,断言错误将告诉你实际得到了什么。我认为将你在ctor中生成的任务作为你的编写者状态的一部分不会有什么坏处。现在,如果我正确地阅读了您的代码,您几乎可以脱离对它的任何控制。您可能可以将其升级为属性,这将为您提供所要求的单元测试中的级别控制,但有一点需要注意:您仍然必须推迟任务,正如您所说的
    [TestMethod()]
    public void GetBufferConsumptionTest()
    {
        StringWriter sw = new StringWriter();
        ResultWriter target = new ResultWriter(sw, 100);
        Assert.IsTrue(target.GetBufferConsumption() == 0);
    
        //here somehow pause the internal task
    
        foreach (var i in Enumerable.Range(1, 5))
        {
            target.Add(i+"");
        }
        Assert.IsTrue(target.GetBufferConsumption() == 5, "Wrong result message");
    
        //here somehow resume the internal task
    
        //somehow wait for the task to consume all 5 items - not relevant for this question
    
        Assert.IsTrue(target.GetBufferConsumption() == 0, "Wrong result message2");
    }