强制仅在某些代码中使用的特定构造函数,而不是其他任何地方

时间:2016-11-15 13:31:38

标签: c++ unit-testing c++11 mocking access

有时,我们需要提供仅用于测试用途的特定构造函数。我们如何强制这样的构造函数仅用于测试代码,而不是其他任何地方。 我只是想知道这是否可以在c ++ 11/14中实现。例如,

class A {
public: 
  A() = default; // used only in test code
}
class A_Test : public ::testing::Test {
 private:
  A a; // it is ok.
};
class A_Production {
 private:
  A a;  // compiler error
}

我可以想象使用friend装饰器并将特定构造函数放在protected中以限制访问。但遗留代码中还有其他现有的朋友。是否可以在c ++ 1x中创建类似protected的自定义说明符?

任何想法?

3 个答案:

答案 0 :(得分:3)

您可以使用Passkey Idiom

您可以通过A提供的A_Test来限制ConstructorKeyA的访问权限,ConstructorKey在其所需的界面中使用class A { class ConstructorKey { friend class A_Test; private: ConstructorKey() {}; ConstructorKey(ConstructorKey const&) = default; }; public: // Whoever can provide a key has access: explicit A(ConstructorKey); // Used only in test code }; class A_Test : public ::testing::Test { private: A a {ConstructorKey{}}; // OK }; class A_Production { private: A a {ConstructorKey{}}; // Compiler error }; ,而不是直接友谊。 {{1}}的朋友可以访问。

{{1}}

答案 1 :(得分:1)

我可以想到几种方法。

  1. 创建构造函数protected,只使用测试子类。

  2. 向某个虚拟类class TestClassThatShouldNotBeUsedInProductionCode;添加前向声明,然后声明一个构造函数,该构造函数将此类的引用作为参数:

    A::A( /* other constructor arguments */,
          const TestClassThatShouldNotBeUsedInProductionCode &)
    
  3. 这个构造函数可以完全忽略这个参数。您的测试模块可以定义这个虚拟的空类:class TestClassThatShouldNotBeUsedInProductionCode {};,并且能够使用它构建您的A类。只有你的测试模块能够使用这个构造函数,然后,它的名称使得它的目的非常明确。没有任何方法可以将某些翻译单元定义为“真实”代码与“测试”代码,在C ++中,您只想实施一个难以意外违反的明确策略。

    有些变体是可能的,例如使用内部类而不是前向声明独立类。内部类只能由测试代码实例化。

答案 2 :(得分:-1)

作为替代方案,在执行A:

测试的cpp文件中
#define private public
#include "ClassA.h"

// ready for testing :)