如何使用UnitTest ++从测试中访问私有类字段?

dav*_*dag 13 c++ unit-testing unittest++

在使用UnitTest ++对单元测试进行编码时,我正面临着麻烦.我想知道如何以干净的方式(或者任何方式......)访问私有成员类字段

到目前为止,我有一个解决方案,使用派生自被测试类的类夹具访问受保护的成员.以下代码显示了这个想法:

struct MyFixture : ClassUnderTest { };

TEST_FIXTURE(MyFixture, OneTest)
{
    do_something();
    CHECK(protected_field == true);
}
Run Code Online (Sandbox Code Playgroud)

尽管如此,我认为这不是很干净,因为在某些配置中可能会出现与继承有关的问题,无论如何,只有受保护的成员才能被访问和测试.

我试图将测试类声明为朋友,但由于这些是由UnitTest ++以某种特殊方式创建的,我还没有设法做到这一点.

有没有人知道如何让测试类成为被测试类的朋友?

是否有另一种方式以更容易或不同的方式解决这个问题?

谢谢大家.

Kor*_*icz 14

有一个非常丑陋但令人惊讶的有用黑客,我通常用于单元测试:

#define private public
#define protected public

#include "class_to_be_tested.h"

// and here, all class's methods and fields are public :P
Run Code Online (Sandbox Code Playgroud)

除了单元测试之外,请勿将其用于其他任何事情!

此外,这种方法有一些限制 - 首先,并非所有私有都带有前缀private.其次,一个流行的编译器将访问说明符变为链接符号.

另一种,也不是那么好的方法是通过铸造.您创建的结构具有相同的字段,但都是公共的,并将其强制转换为指向您的私有结构的指针.然而,这有缺点,类需要完全匹配:

class my_class
{
private:
   char name[40];
   char grade;
   int age;
public:
   //
}

struct my_class_hack
{
public:
   char name[40];
   char grade;
   int age;

}

struct hack_it* my_class_hacked = (my_class_hack*)ptr;
Run Code Online (Sandbox Code Playgroud)

...如果编译器使用您的代码,您可能会得到令人讨厌的惊喜,所以永远不要将它用于生产代码.

  • @Dmitry:一旦你进入现实世界,你就会发现神秘的"客户端"永远不会让你抽出时间来编写"更好的代码",但是需要98%的代码覆盖率 - 这就是你学会爱的时候和价值这样的黑客.我也直接警告说这是一个**丑陋的**黑客. (4认同)
  • -1仅适用于黑客攻击.对不起,为什么不尽可能使代码更好而不是使用黑客? (2认同)

Dmi*_*try 6

单元测试就是通过对象的公共界面测试对象。可能很难做到这一点的事实就是为什么有时将可测试的代码称为art。并非每个人都可以立即编写可测试的代码,这就是为什么人们发明了先编写测试的XP方法的原因。听起来不现实,可以实际运行。

但是,如果您绝对需要测试私有函数,则可以按照自己的喜好选择以下方法列表:

  1. 私有成员变量将通过公共设置方法和获取方法进行访问。

  2. 我建议您使私有成员函数成为可称为例如或的命名空间中的非静态非成员函数。不要在头文件中声明它,而只需在定义类函数的文件中定义它。在单元测试项目的头文件中添加其声明并进行测试。所涉及的困难在很大程度上取决于架构的复杂性。detailsinternalmyClass_internal.h

  3. 使您的测试类继承自可测试的类。这并不需要太多更改代码,但是可能需要使用多重继承,在某些地方甚至禁止这样做。

  4. 让您的测试成为您可测类的朋友。难度取决于您使用的测试框架。说,用我使用的gtest,这很难:)

  5. 如果其他所有方法均失败,那么重新定义公共和私有的hack 绝对是您的最后选择尽管我宁愿考虑将设计更改为更具可测试性的设计。