HippoMocks 是线程安全的吗?

Is HippoMocks thread-safe?

可以像这样在并发测试用例中使用 HippoMocks 吗:

  1. 同步启动阶段

    • 创建模拟
    • 登记期望等
  2. 并行测试阶段

    • 在 mock 上调用方法
  3. 同步拆卸阶段

    • 验证模拟

我没有找到关于这个问题的明确声明。在这里和那里提到,模拟非虚方法会破坏线程安全的可能性(HippoMocks: is it possible to mock non-virtual methods?) or that thread-safety could be added quite easily (unfortunately without actually revealing how). GoogleMock answers this question very clearly (https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md#using-google-mock-and-threads),这样的信息在这里也会有帮助。

不,HippoMocks 没有设计成线程安全的。

但是,如果您遵循一些简单的规则,您应该能够在多线程环境中使用模拟:

  1. 在一个线程中按顺序进行设置并使用一个 MockRepository。
  2. 在不同的线程中使用不同的模拟应该是安全的。
  3. 当您仅使用 OnCall() 设置时,在不同线程中使用一个模拟是安全的。将它与 OnCall().Do() 结合使用,您应该可以通过这种方式进行大量测试。
  4. 不要使用 ExpectCall - 它不安全。

更新: 好的,我做到了。我写了一个多线程的小测试

class IMulti
{
public:
    virtual void A() =0;
    virtual int B(int a) = 0;
};

const int THREAD_ITERATIONS = 1000;

static DWORD WINAPI run_thread(LPVOID args)
{
    IMulti* im = static_cast<IMulti*>(args);
    for (int i=0; i<THREAD_ITERATIONS; i++)
    {
        im->A();
        int result = im->B(22);
        std::cout << "task says: " << i <<" result:" << result <<"\n";
    }

    std:: cout << "finished";

    return 0;
}

TEST(check_HippoMocksCanMultiThreadedConcurrentReadingViaOnCall)
{
    MockRepository mocks;

    IMulti* im = mocks.Mock<IMulti>();

    mocks.OnCall(im, IMulti::A);
    mocks.OnCall(im, IMulti::B).Return(4711);

    HANDLE handles[2];

    handles[0] = CreateThread(NULL, 0, &run_thread, im, 0, NULL);
    handles[1] = CreateThread(NULL, 0, &run_thread, im, 0, NULL);

    WaitForMultipleObjects(2, handles, TRUE, INFINITE);
}

结果是,它工作正常。 现在我让它变得更难一些,并将第二个 OnCall 替换为以下内容:

for (int i = 0; i< THREAD_ITERATIONS*2; i++)
{
    mocks.ExpectCall(im, IMulti::B).Return(i);
}

在这里你会随机发生崩溃(只需玩弄 THREAD_ITERATIONS 计数器)。原因是,匹配的期望以某种方式计算在 Mockrepository 中。

正如预期的那样,同时进行设置会崩溃。