C++单元测试三:测试private成员

来源:互联网 发布:cpa刷量软件 编辑:程序博客网 时间:2024/06/05 19:30

测与不测之争

关于类的私有成员(数据和方法),要不要进行单元测试之争,尚没有统一的结论;(关于这一争论,可以参考http://stackoverflow.com/questions/9202862/is-unit-testing-private-methods-a-good-practice)

有人认为测试私有成员也是一个好的实践,原因嘛,就是没有原因,你本来就应该测你的所有代码;也有人说,类的私有成员根本就不应该测试,单元测试只需要测试对外暴露的接口即可;如果你有对私有成员进行测试的需求,那说明你的设计做的不够好;他们的建议是:将这些私有的方法,重新组织到一个Impl类里面,然后公开这些方法;在原有的类里面,再来使用Impl类暴露的方法。

其实我赞成“应该测试”这样一种说法;原因如下:

  •  一个类,除了对外的接口之外,本身就封装、隐藏了很多实现的细节,这个OO的特性之一。(也有观点认为,封装是TDD的天敌:http://jasonmbaker.wordpress.com/2009/01/08/enemies-of-test-driven-development-part-i-encapsulation/)
  • 如果将所有的private方法重新组织到一个Impl类里面,然后公开这些方法,事实上就暴露了实现的细节;你怎么去保证这些Impl类不会被直接使用呢?
  • 即使你的Impl类,总应该有一些private的数据成员吧,也就是类的状态,这些状态值,又如何来进行确认呢?例如类内部有一个计数器,它仅仅在内部使用,因此不需要定义个getter,public方法调用后,这个计数器的状态是否正确?如果不对这些private成员做测试,如何确认他们的正确性呢?

因此,在需要对private进行测试的时候,就测吧。

如何测试私有成员

不过,成员既然是private的,也就是不太愿意让外面的家伙看到的家丑,又怎么进行测试呢,主要由这样几种方法:

  1. 最简单的,使用#define private public粗暴地将private变成public,不过这要放在#include头文件之前。如:

    #define private public  

    #include “myclass.h”

  2. 使用friend。这个会相对友好一点,但是却需要修改原有的代码。
  3. 使用一些旁门左道,例如:

    • a.      在知道类对象内存布局的情况下,通过地址偏移直接操作地址访问类的数据成员;
    • b.     创建一个具有完全相同内存布局的Dummy类,然后进行强制转换并访问数据。例如

class Data{  public:    int GetValue() { return m_value; };  private:    int m_value;};class DummyData{  public:    int GetValue() { return m_value; };  public:    int m_value;};void AccessPrivateMember(){Data data; /// Data::m_value is not accessible// Here comes the ugly hackDummyData* pDummy = reinterpret_cast<DummyData*>(&data);pDummy->m_value = 17;// Print out the valuestd::cout << data.GetValue() << std::endl;}

方法一最简单也最粗暴;方法二文雅点,但要修改原代码;方法三系出非名门,且只对数据成员有效;

原创粉丝点击