访问私有变量的单元测试
Unit test accessing private variables
我有一个单元测试类Tester
;我想让它访问Working
类的私有字段。
class Working {
// ...
private:
int m_variable;
};
class Tester {
void testVariable() {
Working w;
test( w.m_variable );
}
}
我有以下选项:
- make m_variable
public
- ugly - make method
test_getVariable()
- overcomplicated - 将
friend class Tester
添加到Working中-然后Working明确地"知道"测试器,这是不好的
我的理想是
class Working {
// ...
private:
int m_variable;
friend class TestBase;
};
class TestBase {};
class Tester : public TestBase {
void testVariable() {
Working w;
test( w.m_variable );
}
}
where Working知道TestBase,但不知道每个测试…但这行不通。很明显,继承了遗产,友谊就不成立了。
这里最优雅的解决方案是什么?
我同意Trott的回答,但有时您会将单元测试添加到不适合它的遗留代码中。在这些情况下,我会选择#define private public
。它只适用于单元测试,并且只适用于重构成本太高而不愿费心的时候。这是丑陋的,技术上是非法的,但非常有效。
一般来说,单元测试不应该计算私有变量。把测试写在接口上,而不是实现上。
如果您确实需要检查私有变量是否具有特定的特征,请考虑使用assert()
,而不是尝试为它编写单元测试。
一个更长的答案(为c#而不是c++编写,但适用相同的原则)是https://stackoverflow.com/a/1093481/436641。
-fno-access-control
如果您只使用GCC,您可以在编译单元测试时使用编译器选项-fno-access-control
。这将导致GCC跳过所有访问检查,但仍然保持类布局相同。我不知道其他编译器是否有类似的选项,所以这不是一般的解决方案。
尽量使用公共接口测试所有私有代码。这不仅减少了最初的工作量,而且当更改实现时,单元测试仍然工作的可能性要高得多。
也就是说,有时您只需要戳一下内部就可以获得良好的测试覆盖率。在这种情况下,我使用一种称为expose的习惯用法。如果你仔细想想,这里面有个笑话。
需要测试的Foo类
class Foo
{
public:
// everyone is on their honor to only use Test for unit testing.
// Technically someone could use this for other purposes, but if you have
// coders purposely doing bad thing you have bigger problems.
class Test;
void baz( void );
private:
int m_int;
void bar( void );
};
foo_exposed.h只对单元测试代码可用。
class Foo::Test : public Foo
{
public:
// NOTE baz isn't listed
// also note that I don't need to duplicate the
// types / signatures of the private data. I just
// need to use the name which is fairly minimal.
// When i do this I don't list every private variable here.
// I only add them as I need them in an actual unit test, YAGNI.
using Foo::m_int;
using Foo::bar;
};
// yes I'm purposely const smashing here.
// The truth is sometimes you need to get around const
// just like you need to get around private
inline Foo::Test& expose( const Foo& foo )
{
return * reinterpret_cast<Foo::Test*>(
&const_cast<Foo::Test&>( foo )
);
}
如何在单元测试代码中使用
#include "foo_exposed.hpp"
void test_case()
{
const Foo foo;
// dangerous as hell, but this is a unit test, we do crazy things
expose(foo).m_int = 20;
expose(foo).baz();
}
如果您必须这样做,您可以有条件地编译您的代码,使TestBase仅在单元测试时是友元:
class Working {
// ...
private:
int m_variable;
#ifdef UNIT_TESTING
friend class TestBase;
#endif
};
我通过在我的测试中使用缺少"private"访问说明符的类头文件的副本来做到这一点。副本由测试目录中的makefile生成,以便在原始更改时重新生成副本:
perl -ne 'print unless m/private:/;' < ../include/class_header.h > mock_class_header.h
和'test' make target依赖于mock_class_header.h。
这将授予对测试中所有私有成员变量的访问权,即使真正的库是用这些私有成员变量编译的。
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- 在子目录中使用target_sources()命令时用于单元测试(qtest)的项目结构
- VC++本机单元测试,找不到调试符号
- 用于交叉编译和CMake的预处理器宏的单元测试
- C++ 用于单元测试的模板模板
- 提升 1.64 单元测试编译失败
- 单元测试欧拉到四元数实现失败
- 运行 C++ 单元测试时LNK2005链接错误
- 禁用自动捕获 Googletest 单元测试中的C++异常
- 有没有办法在不使用 #ifdef 的情况下不编译发布版本中的单元测试函数体?
- 使用 Google Test 对自定义断言函数进行单元测试
- 如何将我的 CMake 项目配置为运行所有单元测试?
- 如何在提升构建中设置环境变量以进行提升单元测试框架?
- 使用 gtest 框架在单元测试代码中检查目标对象的私有变量的最佳实践是什么?
- 如何对私有变量是否已更改进行单元测试
- 单元测试呼叫实例变量的函数
- 单元测试一个变量的true和false
- Xcode C++全局变量的单元测试
- 访问私有变量的单元测试
- 如何跨多个单元测试使用用户输入变量