单元测试访问私有变量

Jak*_* M. 8 c++ unit-testing

我有一个单元测试课Tester; 我希望它访问Working类的私有字段.

class Working {
    // ...
    private:
    int m_variable;
};

class Tester {
    void testVariable() {
        Working w;
        test( w.m_variable );
    }
}
Run Code Online (Sandbox Code Playgroud)

我有以下选择:

  • 使m_variable public- 丑陋
  • make方法test_getVariable()- 过于复杂
  • 添加friend class Tester到工作 - 然后明确地工作"知道"测试器,这是不好的

我的理想是

class Working {
    // ...
    private:
    int m_variable;

    friend class TestBase;
};

class TestBase {};

class Tester : public TestBase {
    void testVariable() {
        Working w;
        test( w.m_variable );
    }
}
Run Code Online (Sandbox Code Playgroud)

Working知道TestBase而不是每个测试......但它不起作用.显然友谊不适用于继承.

这里最优雅的解决方案是什么?

Tro*_*ott 16

通常,您的单元测试不应评估私有变量.将测试写入接口,而不是实现.

如果您确实需要检查私有变量是否具有特定特征,请考虑使用assert()而不是尝试为其编写单元测试.

更长的答案(为C#而不是C++编写,但适用相同的原则)在/sf/answers/76543701/.

  • 这样的陈述(一个不应该测试私有接口)让我感到困惑.让我稍微探讨一下:例如,当一个工厂在所有客户发布它们时应该将借出的资源返回到空闲池.由于不需要向客户端公开池状态,因此它是私有的.如何在这样的情况下验证正确的行为?(根据行为发生变化的任何情况,如果有人后来出现并实施了不同的方案,我希望这些测试需要重构.实际上,他们会点亮红色并告诉实施者,这将是设计的.) (3认同)

Mic*_*fik 15

我同意Trott的回答,但有时您会将单元测试添加到非为其设计的遗留代码中.在那些情况下,我伸手去拿#define private public.它只是在单元测试中,而且只是因为重构过于昂贵而无法理解.这是丑陋的,技术上非法,非常有效.

  • 真?这改变了允许测试从需要它的代码编译的魔力.我不想在某个地方的构建系统中埋葬那种东西.我喜欢我丑陋的黑客前面和中心,每个人都可以看到它们. (4认同)
  • 并且,如果您在需要它的'包含'之后立即"#undef private",您可以将损坏限制在一个地方. (3认同)
  • 即使这样,我也会使用`-D private = public`或类似的编译语句. (2认同)
  • 哈哈,[如果约翰卡马克能做到,你也能!](https://github.com/TTimo/doom3.gpl/blob/master/neo/game/Game_local.h) :D (2认同)
  • @Kristo说得对.**遗留代码**的初始测试不是真正的单元测试.这是一个测试,因此当您更改依赖关系等时,您可以确信您没有破坏代码. (2认同)

def*_*ode 5

-fno-access-control

如果您只使用 GCC,则可以-fno-access-control在编译单元测试时使用编译器选项。这将导致 GCC 跳过所有访问检查,但仍保持类布局相同。我不知道其他编译器是否有类似的选项,所以这不是一个通用的解决方案。