c# – 单元测试多线程代码时出现问题

我已经实现了一个Pipe类,它在内部使用BlockingQueue来存储它接收的数据.

BlockingQueue阻塞调用线程有两种情况:

>调用线程调用Dequeue()并且队列为空.它会阻塞线程,直到有一个要检索的项目.
>调用线程调用Enqueue()并且队列已满.它将阻塞线程,直到再次有空间插入数据.

我最初的想法是,不是让Pipe类实例化BlockingQueue,而是通过构造函数注入将IQueue的实例传递给它.这样,在测试时,我会传递一个NonBlockingQueue的实例,所以我不必为线程问题而烦恼(当我正在为Pipe类和其他使用Pipes的类进行单元测试时)我想把这些东西添加到队列中,而不必考虑它们是否已经满了,以及类似的东西.

问题在于,当我这样做时,我实际上使我的管道以两种完全不同的方式运行,具体取决于我传递给它的IQueue实例的类型:

>在BlockingQueue中,如果队列是
空,你试图检索
它的一些东西,它会阻止直到
它有所收获.在一个
NonBlockingQueue它只会呕吐
一个例外.
>在BlockingQueue中,如果队列已满并且您尝试添加某些内容,它将等待有人将某个元素出列并再次存在空间. NonBlockingQueue版本将抛出FullQueueException或允许“无限”数量的元素.

也就是说,没有“单一合同”.我认为这种做法绝对是错误的.

对此更合适的方法是什么?

编辑到米奇:

这用于实现Pipe& Filter系统:每个Filter都有一个输入和输出管道.
然后使用表单的代码实现每个过滤器

char c;
while ((c = inputPipe.ReadChar()) != STREAM_TERMINATOR) { 
//I don't have to care 
//if right now there is any data. I know that if there isn't, 
//the thread will block and this will continue after there is some.

    ...do processing
    outputPipe.WriteChar(something);
}
outputPipe.WriteChar(STREAM_TERMINATOR);

所以我想是的,阻塞管道/队列是我想要的行为.

最佳答案 单元测试的想法是你测试一小部分代码,并且很多代码最终测试你的所有代码.有一个原因,它被分解成碎片,一次测试一件比同时测试一切更容易.在代码中你使用BlockingQueue,并且在测试中使用NonBlockingQueue,它引入了各种具有挑战性的方面,这违背了单元测试的目的……在测试中你应该简化,而不是复杂化.那么为什么不在那里使用BlockingQueue呢?您声明线程可能是一个问题,但至少使用一个简单的IQueue实现,它从外部工作就像一个BlockingQueue,但没有线程问题.在单元测试中,您应该能够在IQueue中提供不会抛出异常的实例.例如,由于队列为空,而不是通常抛出异常,而是提出一个新项目.这是允许的测试….

点赞