不,HippoMocks 的设计不是线程安全的。
但是,如果您遵循一些简单的规则,您应该能够在多线程环境中使用模拟:
- 在一个线程中按顺序进行设置并使用一个 MockRepository。
- 在不同的线程中使用不同的模拟应该是安全的。
- 当您仅使用 OnCall() 设置时,在不同线程中使用一个模拟是安全的。将它与 OnCall().Do() 结合使用,您应该可以通过这种方式进行大量测试。
- 不要使用 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。
正如预期的那样,同时进行设置会崩溃。