单元测试析构函数有什么好方法吗?就像说我有一个这样的类(人为的)例子:
class X { private: int *x; public: X() { x = new int; } ~X() { delete x; } int *getX() {return x;} const int *getX() const {return x;} };
是否有任何好的方法对它进行单元测试以确保x被删除而不会使用#ifdef TEST或破坏封装来混乱我的hpp文件?我看到的主要问题是很难判断x是否真的被删除了,特别是因为在调用析构函数时对象超出了范围.
对依赖注入可能有一些说法.该构造函数不是在构造函数中创建一个对象(在这种情况下是一个int,而是在非设计的情况下更可能是用户定义的类型),而是将该对象作为参数传递给构造函数.如果稍后创建对象,则将工厂传递给X的构造函数.
然后,当您进行单元测试时,传入一个模拟对象(或创建模拟对象的模拟工厂),析构函数会记录它已被调用的事实.如果不是,则测试失败.
当然你不能模拟(或以其他方式替换)内置类型,所以在这种特殊情况下它没有用,但如果你用一个接口定义对象/工厂那么你就可以.
正如其他人所说,在单元测试中检查内存泄漏通常可以在更高级别进行.但是,这仅检查一个析构函数被调用,它并不能证明正确的析构函数被调用.因此,它不会例如在x成员类型的析构函数上捕获缺少的"虚拟"声明(再次,如果它只是一个int则不相关).
我认为你的问题是你当前的例子是不可测试的.既然你想知道是否x
被删除了,你真的需要能够x
用模拟替换.对于一个int来说这可能有点OTT,但我想在你真实的例子中你还有其他类.为了使其可测试,X
构造函数需要请求实现int
接口的对象:
templateclass X { T *x; public: X(T* inx) : x(inx) { } // etc };
现在,模拟值的变得简单x
,并且mock可以处理正确销毁的检查.
请不要注意那些说你应该打破封装或者使用可怕的黑客以便产生可测试代码的人.虽然经过测试的代码确实优于未经测试的代码,但可测试的代码是最好的,它总是能够产生更清晰的代码,更少的黑客攻击和更低的耦合.