2

我想测试当从多个线程调用一个方法时,没有并发问题。我模拟该方法同时调用 3 次,并在我的缓存中插入 2000 个客户,以确保不存在并发问题。

public void Should_Insert_2000_Customers_Using_Concurrency()
{
    var fakeCustomers = InitCustomersFromDb();
    Action insertCustomersFrom_0_to_1000 = new Action(() => 
    {
        Parallel.For(0, 1000, x =>
        {
            CustomerCache.Instance.SetCustomer(x.ToString(), fakeCustomers[0]);
        });

    });
    Action insertCustomersFrom_1000_to_2000 = new Action(() => 
    {
        Parallel.For(1000, 2000, x =>
        {
            CustomerCache.Instance.SetCustomer(x.ToString(), fakeCustomers[0]);
        });
    });
    Action insertCustomersFrom_0_to_2000 = new Action(() => 
    {
        Parallel.For(0, 2000, x =>
        {
            CustomerCache.Instance.SetCustomer(x.ToString(), fakeCustomers[0]);
        });
    });
    List<Task> tasks = new List<Task>();
    tasks.Add(Task.Factory.StartNew(insertCustomersFrom_0_to_1000));
    tasks.Add(Task.Factory.StartNew(insertCustomersFrom_1000_to_2000));
    tasks.Add(Task.Factory.StartNew(insertCustomersFrom_0_to_2000));

    Task.WaitAll(tasks.ToArray());
    var customers = CustomerCache.Instance.GetCustomers();
    Assert.That(customers.Count == 2000);
}

对我运行多个同时Parallel.For迭代CustomerCache是否能有效地显示任何并发问题?

4

2 回答 2

3

IMO,这种测试并没有透露太多。当然,对于这种特殊情况,很明显结果最终将是正确的,但在一般情况下,您同时在集合中插入项目,测试实际添加的项目数量会产生误导,因为得到你expect 并不排除某处存在数据竞争并且您只是“走运”的可能性。

于 2012-07-09T10:03:16.703 回答
1

测试需要测试特定场景。并发测试需要创建一个并发问题,而不是希望一个问题发生。测试应该需要一次运行。如果这在您的代码中很困难,请记住那里的功能代码比可测试的代码多得多。但是......为了降低风险......你想让你的代码可测试。

因此,请确定“并发”的含义并使其发生。要有主见。调用一个方法并模拟它正在调用的内容。当它调用一些告诉你它在关键部分的东西时,然后使用模拟框架来调用另一个调用。

您现在可能想知道“但这意味着多个线程”。线程是一个概念,注入用于创建线程的对象和处理冲突的任何东西。

你一定是在看一两行,然后想……“两个人能做到这一点吗”。测试守卫。

于 2012-07-09T10:02:34.783 回答