【问题标题】:Is HippoMocks thread-safe?HippoMocks 是线程安全的吗?
【发布时间】:2016-08-04 23:56:59
【问题描述】:

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

  1. 同步启动阶段

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

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

    • 验证模拟

我没有找到关于这个问题的明确声明。到处都提到,模拟非虚拟方法会破坏线程安全(HippoMocks: is it possible to mock non-virtual methods?)的可能性,或者可以很容易地添加线程安全(不幸的是没有实际透露如何)。 GoogleMock 非常清楚地回答了这个问题 (https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md#using-google-mock-and-threads),这样的信息在这里也会有所帮助。

【问题讨论】:

    标签: multithreading unit-testing mocking hippomocks


    【解决方案1】:

    不,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。

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

    【讨论】:

    • Hippomocks 使用 MockRepoInstanceHolder,其中包含 MockRepository 的唯一(静态)实例,如回答者所述,这使得 Hippomocks 是非线程安全的。
    • 它仅使用 C 函数上下文中的 MockRepoInstanceHolder,否则无法存储模拟 repo。所有常规模拟都有自己的实例指针,该指针是从 vtable 中检索的。请注意,模拟存储库的其余部分不是线程安全的。
    猜你喜欢
    • 2021-10-12
    • 2015-04-18
    • 2011-10-07
    • 2012-03-02
    • 2011-10-28
    • 2023-03-14
    • 2016-08-24
    • 2011-08-16
    • 2011-09-28
    相关资源
    最近更新 更多