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)开始消耗它们,这会产生一种随机的缓冲区计数
到目前为止,我考虑了以下选择:
writer.WriteLine代码>这已经在以下行之后:foreach(buffer.getconsumineGenumerable()中的字符串s)
,它实际上已经使用了缓冲区中的第一个项。现在有一个测试增加了5个项目,然后仅仅因为上面的原因就期望有4个项目,这似乎远远不够优雅
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");
}