Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用UnitTest+;从测试访问私有类字段+;?_C++_Unit Testing_Unittest++ - Fatal编程技术网

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

C++ 如何使用UnitTest+;从测试访问私有类字段+;?,c++,unit-testing,unittest++,C++,Unit Testing,Unittest++,我在使用编写单元测试代码时遇到了麻烦。我想知道如何以干净的方式(或者任何方式)访问私有成员类字段 到目前为止,我已经有了一个解决方案,可以使用从被测类派生的类fixture来访问受保护的成员。下面的代码显示了这个想法: struct MyFixture : ClassUnderTest { }; TEST_FIXTURE(MyFixture, OneTest) { do_something(); CHECK(protected_field == true); } 尽管如此,我

我在使用编写单元测试代码时遇到了麻烦。我想知道如何以干净的方式(或者任何方式)访问私有成员类字段

到目前为止,我已经有了一个解决方案,可以使用从被测类派生的类fixture来访问受保护的成员。下面的代码显示了这个想法:

struct MyFixture : ClassUnderTest { };

TEST_FIXTURE(MyFixture, OneTest)
{
    do_something();
    CHECK(protected_field == true);
}
尽管如此,我认为这并不是很干净,因为在某些配置中可能会出现与继承相关的问题,而且,无论如何,只能访问和测试受保护的成员

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

有人知道如何让测试类成为测试类的朋友吗

有没有其他更简单或不同的方法来解决这个问题


提前谢谢大家。

有一个非常难看但非常有用的hack,我通常用于单元测试:

#define private public
#define protected public

#include "class_to_be_tested.h"

// and here, all class's methods and fields are public :P
不要将它用于单元测试以外的任何事情

此外,这种方法也有一些局限性——首先,并非所有private都以
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;

。。。但是,如果编译器玩弄您的代码,您可能会得到令人不快的惊喜,因此千万不要将其用于生产代码。

几年前,这是一个激烈争论的主题,但普遍接受的结果是,您应该只测试类的外部可见行为,因此,不需要访问其内部数据和行为


虽然这听起来可能没有帮助,但您可以将要测试的类的私有部分提取到新类中,这些类的外部行为就是您要测试的行为。然后,您可以以正常的方式测试这些类,从而改进您的总体设计。

最好避免测试私人物品。为什么要测试一个私有字段?当private_字段设置为无效值时,会出现什么错误?是否可以测试这种错误的行为,而不是断言错误的值

其他选择包括

  • 在编译代码进行单元测试时,使用预处理器将其公开

  • 将私有字段和相关逻辑提取到一个新类中,该类将是公共的,并使被测类依赖于这个新类


单元测试就是通过对象的公共接口来测试对象。编写可测试代码有时被称为艺术,这可能很难。不是每个人都能立即编写可测试代码,这就是为什么人们发明了XP方法来首先编写测试。听起来不切实际,在现实中起作用

但是,如果您绝对需要测试私有函数,下面是我根据自己的喜好考虑的方法的列表:

  • 私有成员变量通过公共setter和getter访问

  • 我建议将私有成员函数设置为命名空间中的非静态非成员函数,可以调用这些函数,例如
    details
    internal
    。不要在头文件中声明它,只需在定义类函数的同一文件中定义它。将其声明添加到单元测试项目的
    myClass_internal.h
    头文件中,并对其进行测试。所涉及的困难很大程度上取决于体系结构的复杂性

  • 使测试类从可测试类继承。这并不需要对代码进行太多更改,但可能需要使用多重继承,在某些地方甚至是禁止的

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

  • 如果其他一切都失败了,重新定义公共和私人的黑客应该是你绝对的最后手段尽管我更愿意将设计更改为更易于测试的设计。

  • 我也会选择定义黑客

    但也可以使用#define class struct来将隐式私有类数据也公开

    我不同意德米特里的观点:

    1.)这会将接口添加到我的生产代码中,仅用于测试,并且会违反我的封装。我不希望客户端访问我的私人数据

    2.)同样如1.)所示->如果这些接口确实仅用于测试,那么这是个好主意

    3.)只有在访问受到保护时才起作用,这在某种程度上也会影响封装

    4.)还意味着仅为测试而修改我的生产代码,甚至在生产代码和测试代码之间创建耦合


    5.)从您的角度来看,这是正确的,我宁愿使用丑陋的测试代码,而不是丑陋的生产代码:)

    虽然我同意大家说的“不要那样做”,但有时您在一个大型项目中工作,您没有自由对测试中的类进行您想要的所有更改。对于这些情况,我更喜欢朋友声明,而不是公共/私人重新定义黑客

    我想好了该怎么做了 下面是一个“Deck”类的示例,其中包含一个“dealInternal”受保护/私有方法,您希望从“internal”测试中使用该方法


    -1只适用于黑客。对不起,如果可能的话,为什么不让代码变得更好而不是使用黑客呢?@Dmitry:一旦你进入现实世界,你就会知道神秘的
    客户机
    永远不会让你有时间写“更好的代码”,但会要求98%的代码覆盖率——那时候你就可以学会爱和爱了
        //------------- Deck.h -------------
        namespace SuiteDeck { class TestInternals; }
    
        class Deck {
            // etc...
            private:
            friend class SuiteDeck::TestInternals;
            bool dealInternal();
        };
    
        //------------ TestDeck.cpp ----------
        #include "UnitTest++.h"
        #include "Deck.h"
    
        SUITE(Deck) {
            TEST(Internals) {
                Deck d;
                CHECK(d.dealInternal() == true); // or whatever
            }
        }