Google 测试框架:使用阴影方法还是虚拟方法更好?
Google Test Framework: is better to use shadowing or virtual methods?
在下面的示例中,我想对 class A
进行单元测试,以验证在调用 A::request
时,也会调用 B::response()
:
class A
{
public:
void request()
{
m_b.response();
}
private:
B m_b;
};
class B
{
public:
void response();
};
为了做到这一点,class B
必须被嘲笑:
class MockB : public B
{
public:
MOCK_METHOD0( response, void());
};
因此测试将包含:
class TestA : public A
{
...
};
...
EXPECT_CALL( m_b, response( ) ).Times( 1 );
request( );
...
问题是:如何用"inject"MockB
代替B m_b
?
第一个技巧:
创建一个 ShadowB
class 将方法调用重定向到 class MockB
。这需要原始代码在外部二进制文件中,但不需要对实际代码进行任何更改。
第二种技术:
- 制作
B::response
virtual
- 将
B m_b
更改为 std::unique_ptr<B> m_b
- 在测试设置期间用
class MockB
的实例替换 m_b
值
第二种方法意味着更多的代码更改,我不确定它的优点。
解决问题的正确方法是第二种方法。更一般地说,很难 'retro-fit' 将单元测试代码添加到未设计时考虑到它的组件上 - 您几乎总是需要显着修改被测试的代码。
使用虚函数代替真实的模拟回调对象,两者都继承自一个公共接口是一种非常常见的方法。另一种选择是让您的 类 被测试为模板 类,并将其模板参数替换为 Mock 对象。
在下面的示例中,我想对 class A
进行单元测试,以验证在调用 A::request
时,也会调用 B::response()
:
class A
{
public:
void request()
{
m_b.response();
}
private:
B m_b;
};
class B
{
public:
void response();
};
为了做到这一点,class B
必须被嘲笑:
class MockB : public B
{
public:
MOCK_METHOD0( response, void());
};
因此测试将包含:
class TestA : public A
{
...
};
...
EXPECT_CALL( m_b, response( ) ).Times( 1 );
request( );
...
问题是:如何用"inject"MockB
代替B m_b
?
第一个技巧:
创建一个 ShadowB
class 将方法调用重定向到 class MockB
。这需要原始代码在外部二进制文件中,但不需要对实际代码进行任何更改。
第二种技术:
- 制作
B::response
virtual
- 将
B m_b
更改为std::unique_ptr<B> m_b
- 在测试设置期间用
class MockB
的实例替换m_b
值
第二种方法意味着更多的代码更改,我不确定它的优点。
解决问题的正确方法是第二种方法。更一般地说,很难 'retro-fit' 将单元测试代码添加到未设计时考虑到它的组件上 - 您几乎总是需要显着修改被测试的代码。
使用虚函数代替真实的模拟回调对象,两者都继承自一个公共接口是一种非常常见的方法。另一种选择是让您的 类 被测试为模板 类,并将其模板参数替换为 Mock 对象。