C# 从多个线程进行单元测试的最佳方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 09:51:03  来源:igfitidea点击:

Whats the best way to unit test from multiple threads?

提问by Rob Cooper

this kind of follows on from another questionof mine.

这是我的另一个问题的延续。

Basically, once I have the code to access the file (will review the answers there in a minute) what would be the best way to testit?

基本上,一旦我有了访问文件的代码(将在一分钟内查看那里的答案),测试它的最佳方法是什么?

I am thinking of creating a method which just spawns lots of BackgroundWorker's or something and tells them all load/save the file, and test with varying file/object sizes. Then, get a response back from the threads to see if it failed/succeeded/made the world implode etc.

我正在考虑创建一个方法,它只会产生大量的BackgroundWorker或其他东西,并告诉他们所有加载/保存文件,并使用不同的文件/对象大小进行测试。然后,从线程获取响应以查看它是否失败/成功/使世界内爆等。

Can you guys offer any suggestions on the best way to approach this? As I said before, this is all kinda new to me :)

你们能就解决这个问题的最佳方法提出任何建议吗?正如我之前所说,这对我来说都是新鲜的 :)

Edit

编辑

Following ajmastrean'spost:

ajmastrean 的帖子后:

I am using a console app to test with Debug.Asserts :)

我正在使用控制台应用程序来测试 Debug.Asserts :)



Update

更新

I originally rolled with using BackgroundWorkerto deal with the threading (since I am used to that from Windows dev) I soon realised that when I was performing tests where multiple ops (threads) needed to complete before continuing, I realised it was going to be a bit of a hack to get it to do this.

我最初使用BackgroundWorker来处理线程(因为我已经习惯了 Windows 开发人员的线程),我很快意识到,当我执行测试时,需要在继续之前完成多个操作(线程),我意识到这将是让它做到这一点有点技巧。

I then followed up on ajmastrean's post and realised I should really be using the Threadclass for working with concurrent operations. I will now refactor using this method (albeit a different approach).

然后我跟进了ajmastrean的帖子,意识到我真的应该使用Thread类来处理并发操作。我现在将使用这种方法进行重构(尽管是一种不同的方法)。

采纳答案by Anthony Mastrean

In .NET, ThreadPoolthreads won't return without setting up ManualResetEvents or AutoResetEvents. I find these overkill for a quick test method (not to mention kind of complicated to create, set, and manage). Background worker is a also a bit complex with the callbacks and such.

在 .NET 中,ThreadPool如果不设置ManualResetEvents 或AutoResetEvents ,线程将不会返回。我发现这些对于快速测试方法来说太过分了(更不用说创建、设置和管理的复杂性了)。后台工作者对于回调等也有点复杂。

Something I have found that works is

我发现有效的是

  1. Create an array of threads.
  2. Setup the ThreadStartmethod of each thread.
  3. Start each thread.
  4. Join on all threads (blocks the current thread until all other threads complete or abort)
  1. 创建一个线程数组。
  2. 设置ThreadStart每个线程的方法。
  3. 启动每个线程。
  4. 加入所有线程(阻塞当前线程,直到所有其他线程完成或中止)
public static void MultiThreadedTest()
{
    Thread[] threads = new Thread[count];

    for (int i = 0; i < threads.Length; i++)
    {
        threads[i] = new Thread(DoSomeWork());
    }

    foreach(Thread thread in threads)
    {
        thread.Start();
    }

    foreach(Thread thread in threads)
    {
        thread.Join();
    }
}

回答by Eric Z Beard

Your idea should work fine. Basically you just want to spawn a bunch of threads, and make sure the ones writing the file take long enough to do it to actually make the readers wait. If all of your threads return without error, and without blocking forever, then the test succeeds.

你的想法应该很好。基本上,您只想生成一堆线程,并确保写入文件的线程花费足够长的时间来真正让读者等待。如果您的所有线程都没有错误地返回,并且没有永远阻塞,则测试成功。

回答by aku

@ajmastrean, since unit test result must be predictable we need to synchronize threads somehow. I can't see a simple way to do it without using events.

@ajmastrean,由于单元测试结果必须是可预测的,我们需要以某种方式同步线程。如果不使用事件,我看不到一种简单的方法。

I found that ThreadPool.QueueUserWorkItem gives me an easy way to test such use cases

我发现 ThreadPool.QueueUserWorkItem 为我提供了一种测试此类用例的简单方法

 ThreadPool.QueueUserWorkItem(x => { 
    File.Open(fileName, FileMode.Open);
    event1.Set(); // Start 2nd tread;
    event2.WaitOne(); // Blocking the file;
});
ThreadPool.QueueUserWorkItem(x => { 
    try
    {
        event1.WaitOne(); // Waiting until 1st thread open file
        File.Delete(fileName); // Simulating conflict
    }
    catch (IOException e)
    {
        Debug.Write("File access denied");
    }
});