首页 > 解决方案 > 使用 CRTP 和 google 测试框架的库 api

问题描述

我有一个使用CRTP的模板库

// Base configuration to be derived from.
struct TemplateBaseConfig {
    static constexpr auto config_1 = true;
    static constexpr auto config_2 = false;
    static constexpr auto config_val_3 = 42;
};

template <typename Derived_, typename DerivedConfig_, typename... Widgets>
struct TemplateBaseClass {
    std::tuple<Widgets...> widgets;
    // Lots of functions and logic etc.
    void function_1() {
        if constexpr (DerivedConfig_::config_1) {
            // do something
        }
        static_cast<Derived_*>(this)->function_2();
    }
    void function_2() { /*do something*/ }
};

现在用户TemplateBaseClass用作:

// Make a custom config.
struct DerivedConfig : TemplateBaseConfig {
    static constexpr auto config_1 = false;
};

struct DerivedClass : TemplateBaseClass<DerivedClass, DerivedConfig, Widget1, Widget2> {
    void function_2() { /* override base logic */ }
};

TemplateBaseClass通过继承一个MockTemplateBaseClassInterface.

template <typename TestingClass, typename TestingClassConfig, typename... W>
struct MockTemplateBaseClassInterface : TemplateBaseClass<TestingClass, TestingClassConfig, W> {
    // Mock some internal functions which always need to be mocked.
    MOCK(internal_function_1);
    MOCK(internal_function_2);
    // Some custom setup for unittests like override the log dir
    void function_2() { Parent::function_2(); MakeLogDir(); } // Parent is this guy's base class.
}

为给定的编写单元测试DerivedConfig,因此我创建了一个派生类MockTemplateBaseClassInterface

ClassToTestFunction1 : MockTemplateBaseClassInterface<ClassToTestFunction1, TestConfig1, MockWidget> {
    // Write more mock functions if required.
    MOCK(function3);
};

然后我ClassToTestFunction1在一个夹具类中使用来编写单元测试。

这可以完美地测试任何东西,TemplateBaseClass因为我可以给出任何配置,在需要时编写自己的模拟。

现在,如果我必须为最终用户公开这个测试框架以便他可以编写测试DerivedClass,那么前进的方向应该是什么?

我可以要求用户执行以下操作:

    struct DerivedClass :
#ifdef _DOING_TESTING_
 MockTemplateBaseClassInterface<DerivedClass, DerivedConfig, Widget1, Widget2> 
#else
 TemplateBaseClass<DerivedClass, DerivedConfig, Widget1, Widget2>
#endif
 {
        void function_2() { /* override base logic */ }
    };

但是现在用户不能真正模拟TemplateBaseClass的功能。

用户会想要测试他的function_2(). 但是,如果function_2()使用某些功能,TemplateBaseClass他会想模拟它。我的意思是,这就是单元测试的重点,对吧?

标签: c++unit-testingtemplatesgoogletestcrtp

解决方案


推荐阅读