我有定义为在.h文件中
namespace diagnostic{
class class1interface{
virtual int readpowerstate()const =0;
virtual int readparameters() = 0;
}
class class1 : public class1interface{
int readpowerstate()const;
int readparameters();}};
在.cc文件中,我具有功能
int diagnostic::readparameters(){
if(diagnostic::readpowerstate ==1)
{ //Dothis}
else
{return 0}}
我必须执行else部分,因为默认情况下,当我运行程序时会调用if。所以我尝试如下使用gmock。
class Mock_class : public diagnostic::class1interface{
public:
Mock_class(){}
MOCK_METHOD0(readparameters,int());
MOCK_CONST_METHOD0(readpowerstate,int());};
和我编写的gmock测试如下//测试读取参数的失败
TEST_F(TestBase, readParam_failure){
Mock_class mock_class;
class1 *class_dummmy = new class1();
EXPECT_CALL(mock_class, readpowerstate()).WillOnce(Return(0));
class_dummy->readparameters;
EXPECT_EQ(0, class_dummy->readparameters());}
当我执行此程序时,出现以下错误:错误:实际的函数调用计数不匹配EXPECT_CALL(mock_class, readpowerstate())
...预期:至少被调用一次实际:从未致电-不满意和活跃
由于我是gmock的新手,这是什么解决方案?
模块测试都是关于在模拟环境中测试隔离的模块(例如选定类的实例),特别是该模块如何与其他对象通信,以及它如何响应这些调用的各种结果。为了实现这一点,可以使用mocks代替其他real对象。模拟类都允许:
这样就可以测试一个对象,好像它被真实的组件包围了一样,而实际上没有它们。例如,可以通过模拟代表设备的类并进行编程以模拟当管理器调用某些状态功能时返回错误代码的设备管理器,以响应设备故障。即,不使用实际的设备类,也不需要连接(或配置)实际的(有故障!)设备本身。模拟将假装成为该设备,重要的是,所有这些都将在软件级别上进行。
但是,只有当类本身的设计方式允许我们以某种方式inject模仿对象代替它们的真实对应物时,才有可能。最重要的是,系统中的对象需要通过接口和虚拟调用进行通信。也就是说,上述设备管理器不应与DeviceA
(具体的类名)进行通信,而应与某些DeviceInterface
通信,因此DeviceA
和新创建的模拟DeviceMock
均可实现该功能界面并在该管理器中使用。这样,管理器甚至不会知道它正在经过测试,并且不会与模拟对象(而不是真实的设备包装程序)进行通信。
也就是说,尽管您为class1interface
创建了一个模拟,但实际上并没有使用该模拟。相反,您尝试测试class1
。仅当您打算测试通过class1interface
而不是class1
本身与class1interface
进行通信的某些other组件(如类)时,为class1
创建模拟才有用。
所以,有一个class1
的模拟,您可以例如测试class2
。但这需要该类设计满足我之前提到的条件:通过接口进行通信并具有注入模拟类的能力。
为了满足条件,您必须重写代码:
int class2::readdata() { std::unique_ptr<diagnostic::class1interface> classint = std::make_unique<diagnostic::class1>(); int value = classint->readparameters(); return value; }
到(这只是有用性可疑的一个例子,您必须根据需要对其进行调整):
int class2::readdata(diagnostic::classinterface* classint) { int value = classint->readparameters(); return value; }
因此您可以为
class2
编写测试,并注入class1
的模拟物:
TEST_F( TestClass2, readParam_failure ) { // Mocks configuration Mock_class mock_class; EXPECT_CALL( mock_class, readparameters() ).WillOnce(Return(0)); // System under test configuration diagnostic::class2 sut; // Test itself EXPECT_EQ( 0, sut.readdata(&mock_class) ); }
以这种方式检查对
class2::readdata
的呼叫是否正确地转接到class1interface::readparameters
,并返回其结果。