gtest、gmock的使用
GoogleTest
GoogleTest 是由 Google 开发的一个 C++ 单元测试框架,用于编写、组织和运行自动化测试代码。它支持断言(如 EXPECT_EQ
、ASSERT_TRUE
等)、测试夹具(test fixtures)、参数化测试等高级功能,能够帮助开发者在开发过程中快速发现和定位问题。GoogleTest 具有良好的跨平台性,广泛用于 C++ 项目的测试验证,是工业界最常用的 C++ 测试框架之一。
断言
断言是用于单元测试中 验证程序行为是否符合预期 的语法工具。断言会对比测试值和期望值,若不一致,测试会标记失败。
ASSERT_*:当断言失败时,产生致命错误,并终止当前函数;
EXPECT_*:当断言失败时,产生非致命错误,并且不会终止当前函数
基本断言
二元断言
字符串断言
浮点数断言
指针断言
异常断言
注意:这里的statement可以是一段代码,也可以是函数调用,只要能触发一个异常就可以
容器断言
致命错误断言
用于验证代码是否会引发特定的致命错误(通常是程序终止)。
EXPECT_DEATH(statement, regex)
用于测试在执行 statement 时是否会导致程序崩溃,并且崩溃信息是否符合正则表达式 regex 的要求。statement:要测试的代码或函数调用。如果这段代码引发了致命错误,测试会通过regex:用于匹配崩溃信息的正则表达式。这个正则表达式用于检查程序崩溃时输出的错误信息是否符合预期。
致命错误介绍:
①abort()函数用于立即终止程序的执行。
②std::terminate()函数用于终止程序的执行。#include <exception>。它会调用一个终止处理程序,如果没有设置自定义终止处理程序,默认行为是调用abort()。
③std::exit()用于正常或异常终止程序的执行。允许程序指定一个退出状态,并在程序终止前执行所有由atexit()注册的函数清理。
谓词断言
1.EXPECT_PREDn
EXPECT_PREDn(predicate, actual .......n);
predicate:用户定义的谓词函数,可以是一个接收一个或多个参数并返回布尔值的函数
actual:被测试的值或表达式
bool isEven(int x) {return n % 2 == 0;
}
TEST(myTest, checkEven) {EXPECT_PRED1(isEven, 4);EXPECT_PRED1(isEven, 5);
}
2.EXPECT_PRED_FORMAT*
用于使用谓词函数进行条件检查,并允许自定义错误消息的格式化(message)。适用于需要详细错误信息的场景,可以再测试失败时,提供更详细的上下文。
bool AreEqual(int a, int b) {if (a != b) {::testing::Message msg;msg << “Expected” << a << “equals” << b;return false;}return true;
}
TEST(myTest, checkEven) {EXPECT_PRED_FORMAT2(isEven, 4,4);EXPECT_PRED_FORMAT2(isEven, 1,5);
}
SUCCEED
标记当前测试用例成功并立即结束测试。无论之前的测试代码是否存在错误,都会标记为成功,并且SUCCEED后面的代码不会被执行
TEST(MyTestSuite, SucceedExample) {int x = 10;int y = 20;if (x + y == 30) {SUCCEED(); // 满足条件,标记成功,立即结束测试}// 下面这行代码不会被执行FAIL() << "This should not happen!";
}
FAIL
标记当前测试用例为失败并立即结束测试。可以用来在测试代码中发现不可接受的状态时报告测试失败。在FAIL()之后的代码不会被执行。可以FAIL() << “ ”;用于在测试失败后输出一段信息
ADD_FAILURE/ADD_FAILURE_AT
ADD_FAILURE:用于手动添加测试失败的报告,而不依赖于某个特定断言的失败。可以在代码中的任何一个位置来标记,当执行到ADD_FAILUR时,gtest会报告测试失败,但程序仍然会继续执行后续的代码。
ADD_FAILURE_AT:允许在指定的文件名和行号处报告失败。
ADD_FAILURE_AT(__FILE__,__LINE__);__FILE__,__LINE__是c++的宏,表示当前文件和当前行,也可以是其他文件其他行。
EXPECT_THAT(actual, matcher)
用于进行复杂的条件检查,特别是在使用匹配器时。
actual:被测试的值或表达式或对象
matcher:用于检查actual的匹配器。匹配器可以是多种类型,用于执行不同的比较。
int x = 0;
EXPECT_THAT(x, Eq(0));
函数
testing::invoke()
用于在模拟对象的方法或函数时指定具体的行为。它可以将模拟的方法调用委托给一个用户定义的函数或仿函数,从而实现自定义的行为。testing::Invoke() 不仅可以用于普通函数,还可以用于仿函数、lambda 表达式或类成员函数等。Invoke() 通常与 Google Mock(Google Test 的一部分)中的 EXPECT_CALL() 或 ON_CALL() 语句一起使用,允许模拟对象在被调用时执行自定义逻辑,而不是返回默认值或固定的结果。
示例:
假设我们有一个接口 Foo,其中包含一个虚拟函数 DoSomething(),我们可以使用 testing::Invoke() 来指定这个函数在被调用时应该执行的具体行为。
testing::setArgReferee()
用于模拟函数中修改通过引用传递的参数的值。它可以被用来设置一个引用参数(或指针参数)在函数调用后应该持有的值。当我们使用 Google Mock 来模拟一个带有引用参数的函数时,SetArgReferee() 允许我们在该函数调用时修改这些引用参数的值,从而模拟函数的副作用。
基本语法:testing::setargreferee<N>(value);
其中
· N:参数的索引(从 0 开始),表示哪个参数是引用类型,需要被修改。
· value:当函数被调用时,将该值赋给引用参数。
示例:
假设我们有一个接口 Foo,其中包含一个方法 GetValue(int& out_value),它通过引用参数返回一些值。我们可以使用 testing::SetArgReferee() 来模拟这个行为,并设置引用参数的值。
常用宏
TEST()
TEST()第一个参数是Test Case的名称,第二个参数(隶属第一个Test Case参数)Test的名称。
一个测试的完整名称包括Test Case的名称以及Test的名称,不同Test Case的Test名称可以相同。
根据Test Case对测试结果进行分组,相关的test应放在同一个Test Case中
注意:gtest中main函数可以不用自己写,gtest会提供默认的main函数
提供的main示例:
int main(int argc, char **argv) {// 初始化 Google Test 框架testing::InitGoogleTest(&argc, argv);// 运行所有测试用例,并返回结果return RUN_ALL_TESTS();
}
TEST_F()
当我们想让多个test使用同一套数据配置时,就需要用到Test Fixtures了。
创建Fixtures步骤:
(1)派生一个继承testing::Test的类,并将该类(testing::Test)中的一些内容声明为protected类型,以便在子类中进行访问。
(2)根据实际情况,编写默认的构造函数或setup()函数,来为每个test准备所需的数据。
注意:setup()函数用于在每个测试用例运行之前执行更复杂的初始化逻辑,如设置共享数据或配置环境。
(3)根据实际情况,编写默认的析构函数或TearDown()函数,来释放SetUp()中分配的资源
(4)根据实际情况,定义test共享的子程序。
注意:
①TEST_F() 宏允许测试用例访问测试夹具类中的 protected 成员变量和方法,所以如果测试代码中使用了Test Fixtures,应该使用TEST_F代替TEST。
如果你的测试用例在当前的 test.cpp 文件中不需要使用任何继承自 ::testing::Test 的类中的 protected 成员,并且不依赖于测试夹具中的初始化和清理逻辑,那么你可以使用 TEST() 宏,而不必使用 TEST_F() 宏。
②TEST_F()的第一个参数必须是Test Fixture类的名字。
③对于TEST_F()定义的每个test,GoogleTest将会在运行时创建一个新的Test Fixture,并立即通过SetUp()对其进行初始化,然后运行test,之后通过调用TearDown()进行数据清理,最后删除Test Fixture。需要注意的是,同一个Test Case中不同的test具有不同的Test Fixture对象,并且GoogleTest每次创建新的Test Fixture前都会先删除之前的Test Fixture。多个test不会重用相同的Test Fixture,某个test对fixture进行的修改对其他test无影响。
TEST_P()
是gtest中用于参数化测试的宏。通过参数化测试,可以编写一次测试代码,然后不用的输入值多次运行这个测试。
使用步骤:
1.定义一个测试夹具,并使用::testing::TestWithParam<T>来指定参数类型:
class myTestFixture : public ::testing::TestWithParam<int> {};
TEST_P(myTestFixture, checkEven) {int n = GetParam();EXPECT_EQ(n % 2, 0);
}
2.使用INSTANTIATE_TEST_SUITE_P来提供参数组合
INSTANTIATE_TEST_P(EvenTests,MyTestFixture,::testing::Values(2,4,6)
);
注意:除了Values传参外,还有以下几种
①Range(a,b[,step]):传入从a到b- 1的连续参数(或满足步长的间断参数)
②combine(g1, g2 .....):允许将多个参数组合在一起,进行笛卡尔积的参数化测试。这种方式适用于需要多个参数组合的情况。
示例:
class myTestFixture : public ::testing::TestWithParam<std::tuple<int, char>> {};
TEST_p(myTestFixture, checkCombination) {int num = std::get<0>(GetParam());char ch = std::get<1>(GetParam());
}
INSTANTIATE_TEST_SUITE_P(comboTests,myTestFixture,::testing::combine(::testing::Values(1, 2),::testing::Values(‘a’, ‘b’)
)
);
传递的参数是:
RUN_ALL_TESTS()
调用RUN_ALL_TESTS()宏在所有test都成功时,返回0;否则返回1。
RUN_ALL_TESTS()会运行所有关联的test,这些test可以来自不同的test case,甚至不同的源文件
注意:
①main()函数必须要返回RUN_ALL_TESTS()宏的结果。同时,RUN_ALL_TESTS()只能运行一次,多次调用会与GoogleTest的一些功能(如thread-safe、death tests)发生冲突。
②main()函数中的::testing::InitGoogleTest()函数将会解析命令行中的GoogleTest参数
GoogleMock
Google Mock(简称 GMock)是 Google 提供的一个 C++ 模拟框架,通常与 GoogleTest 搭配使用。它用于在测试中创建模拟对象(mock objects),从而隔离被测试代码与其依赖,验证函数调用行为是否符合预期。GMock 支持精细的调用控制(如调用次数、参数匹配、调用顺序等),使得单元测试更加灵活可靠,是编写高质量 C++ 测试不可或缺的工具。
mock作用:mock对象可以用来模拟其他类的行为。即自己实现一个假的依赖类,对这个类的方法行为和返回结果进行自定义。
注意:mock类可以模拟类的protected和private方法。Mock类不是简单地继承原本的接口,然后自己把它提供的方法实现;Mock类其实就等于原本的接口。对protected和private方法的Mock和public基本类似,只不过在Mock类中需要将这些方法设置成public。
使用mock类的一般流程
1.引入googlemock名称空间:引入相关的googlemock宏和函数
2.建立模拟对象:创建 Mock 类来替代接口或虚函数
class MockFoo: public FooInterface
MockFoo mockFoo;
3.设置默认行为通过ON_CALL(可选):为mock设置默认返回值或行为
4.设置期望通过EXPECT_CALL:设置具体的调用期望和行为
5.验证行为:运行测试,根据期望验证模拟对象的调用是否符合预期。
函数
MOCK_METHOD()
模拟类中创建模拟方法,可以处理任意个参数,也可以是mock_method1代表模拟的是一个参数的函数。
注意:mock_method()必须放在mock类的public处声明
基本语法:
MOCK_METHOD(return_type, method_name, (arg_types...), (specifiers));
· return_type:方法的返回类型。
· method_name:方法的名称。
· arg_types:一个括号内的参数类型列表,可以为空,表示无参数。
· specifiers:可选的修饰符,比如 const、override、noexpect、calltype(calltype)、ref(qualifier)等。
其中ref(qualifier)是用给定的引用限定符标记方法,例如ref(&)或ref(&&)。如果重写具有引用限定符的方法则需要。
(&)限定符:指定成员函数只能通过左值对象调用
(&&)限定符:指定成员函数只能通过右值对象调用
左值对象调用指:对象.成员函数()
右值对象调用指:std::move(对象).成员函数()
示例:
EXPECT_CALL()
EXPECT_CALL(mock对象, 方法的名称(匹配器machers))
注意:
- expect_call必须在任何执行模拟对象的代码之前。
- expect_call返回的是一个::tesing::Expecation类型的对象。Expecation表示某个期望调用的类
- ExpectationSet:用于对一组期望(Expectation)进行管理和验证
EXPECT_CALL()可调用(.连接)的方法
.with(multi_argument_matcher)
用于指定多个参数的自定义匹配规则。它可以为expect_call中函数的参数灵活的定义复杂的参数匹配条件
补充:常见比较器
①Args匹配器:将参数提取为多个部分,并在每个部分上应用匹配器
.With(Args<0,1>(ElementsAre(Le(5), Ge(3))));
表示第一个参数小于等于5,第二个参数大于等于3
②Allof匹配器:用于指定多个条件,所有条件都需要满足
.with(Allof( Args<0>(Gt(10)) , Args<1>( lt(20) ) ))
③Field匹配器:允许针对结构体或者类的某个字段进行匹配
struct mystruct {int x;int y;
}
.with(Field(&mystruct::x,Eq(5))));
④Trulu匹配器:可以自定义布尔函数来匹配参数
bool custommatcher(int arg1, int arg2) {return arg1 > arg2;
}
.with(Truly(custommatcher));
.timer(cardinality)
用于指定mock方法期望调用几次
cardinality:
①AnyNumber()表示这个方法可以被调用任意次数
②Between(m,n)表示函数被调用的次数在m和n之间,包含边界
③Atmost(n)、Atleast(n)表示至少之多被调用n次
④Exactly(n) /n表示精确调用次数n
注意:
1.如果没写timers,mock'也会自己推断次数
如果既没有指定willonce也没有指定willrepeatedly,则推断为Timers(1)
如果有n个(n >= 1)willonce子句,而没有willrepeat子句,则推断为Timers(n)
如果有n个(n >= 0)willonce子句,和一个willrepeat子句,则推断为Timers(Atleast(n))
2.timer子句最多只能使用一次
.insequence(sequence....)
用于指定函数调用按照一定顺序进行
序列sequences:默认时定义的期望行为是无序的。
示例:
何时调用getsize()和getvalue()是都可以的,无先后顺序。
EXPECT_CALL(mockFoo, getSize()).InSequence(s1, s2)代表将getsize()放在序列s1和s2中,并且在序列s1和s2中getsize()必须最先执行。而EXPECT_CALL(mockFoo, getValue()).InSequence(s1),把getvalue放在了序列s1中,但由于getsize()先放入的s1,因此在s1中geisize会比getvalue先执行,然后getvalue才执行。
运行结果:
注意:在将函数使用sequences限制后,调用这些函数的顺序必须遵照约定好的,否则会报错。
对于以上示例:可以不使用sequence,而是通过定义一个insequence对象insequence dummy;就能代表下面定义的所有EXPECT_CALL()函数都会按照他们定义的顺序进行执行。
.after(expectations...)
指定模拟函数调用预计在一个或多个其他调用之后发生。参数最多是五个期望值或期望值对象。after子句可以在期望中使用任意次数
示例一:fun()的调用必须在init_x和init_y之后
using ::testing::expectation;
Expectation init_x = EXPECT_CALL(mockObj, Initx());
Expectation intt_y = EXPECT_CALL(mockObj, inity());
EXPECT_CALL(mockObj, fun()).After(init_x, init_y);
示例二:func()的调用必须在ExpectationSet中的所有Expectation执行完才可执行
using ::testing::ExpectationSet;
ExpectaionSet all_inits;
for (int i = 0; i < element_count(); i++ {all_inits += EXPECT_CALL(mockObj, initElement(i));
}
EXPECT_CALL(mockObj, func()).After(all_inits);
.willonce()/.willrepeatedly()
是gmock中常用的行为定义函数,用于模拟函数在被调用时的返回行为或执行动作。主要用于EXCEPT_CALL中控制模拟对象的方法的行为。
willonce
用来指定模拟方法第一次调用时的行为。无论之后该方法被Timer(n)调用多少次,willonce之影响第一次调用。
使用场景:想让某个函数在第一次调用时返回一个值或执行一个动作,而后续的行为则可能不同。它只会影响函数的第一次调用。若函数被调用多次且没有定义后续的行为,gmock将抛出警告,提示多次调用但行为未定义。
注意:
①若没有Timers只使用一个willonce会推断为Timers(1)
②willeonce子句可以在期望中使用任意次数
③与willrepeatet不同,传递给每个willonce调用的操作最多只被调用一次
willRepeatedly
用来定义模拟方法被调用时的默认行为,即函数被多次调用时的重复行为。他会在每次调用时都执行指定的动作,除非有willonce先行覆盖了某些调用的行为。WillRepeatedly 通常用于函数的常规行为定义。如果你期望函数每次调用都返回相同的值或执行相同的动作,可以使用 WillRepeatedly。WillRepeatedly可以与 WillOnce 结合使用,来定义函数的某次调用和后续调用的不同行为。
.RetiresOnSaturation()
用于处理调用次数饱和的情况。当一个EXPEX_CALL()指定的调用次数已经达到上限时,RetiresOnSaturation()允许期望从匹配队列中移除,后续调用不再与该期望匹配,从而不再对后续调用施加影响。
示例:
.on_call(mockObj, methodName(Matchers.....))
用于设置mock方法的默认行为或返回值,特别是在没有明确的期望时,mock对象应该返回什么结果。
注意:
①如果同时使用ON_CALL和EXPECT_CALL,则EXPECT_CALL的行为会覆盖ON_CALL()的默认设置。
on_call可.的方法(子句)
(1).with(mulit_argument_matcher):当方法的参数符合某个条件时,执行某个默认行为/返回,
ON_CALL(mockObj, get).with(Lt(10).willByDefault(Return(42));
ON_CALL(mockObj, get).with(Rt(10).willByDefault(Return(42));
EXPECT_EQ(mock_obj.GetValue(5), 42); // 参数小于10,返回42
EXPECT_EQ(mock_obj.GetValue(15), 100);// 参数大于 10,返回100
注意:ON_CALL是宽松的,如果没有匹配.with()的参数,方法仍然可以被调用,或者继续使用其他默认行为。
(2).WillByDefault(action):用于设置mock方法默认行为的方法。如果ON_CALL本身定义了某个mock方法被调用时的条件(通过.will),则WillByDefault(action)用来指定的当这些条件满足时,该mock方法应执行的默认操作。
注意:
①这里的默认操作可以是返回具体的值,返回动态值,调用真实方法,触发其他行为等。
②每个ON_CALL语句只能使用WillByDefault语句一次。
gTest定义的处理mock的类
DefaultValue ::testing::DefaultValue<T>
为某个类型设置全局的默认返回值
当mock对象的方法被调用时,如果没有明确的EXPECT_CALL()或ON_CALL()定义其返回行为,gmock会尝试返回DefaultValue类中为该类型设置的默认值。使得在没有明确期望的情况下,mock方法仍然可以返回一个有效值,从而避免因未定义行为导致的测试失败。
①DefaultValue<Type>::Set(value):为类型Type设置默认返回值
②DefaultValue<Type>::Clear():清除为类型Type设置的默认返回值,恢复到默认行为(数值类型默认为0,指针类型默认为nullptr,布尔默认为false,引用类型默认返回空对象)
示例:
TEST(... , ...) {::testing::DefaultValue<int>::Set(42);myMock mock;EXPECT_CALL(mock, getnuber()).Times(1);EXPECT_EQ(mock.getnumber(), 42);::testing::DefaultValue<int>::clear();
}
NiceMock ::testing::NiceMock<T>
提供了一个宽容的mock行为
作用1:
在使用NiceMock时,即使没有为某个方法设置明确的期望或默认返回值,调用这些方法时也不会导致测试失败或触发警告。(mock的默认行为:未明确期望(未使用EXPECT_CALL/ON_CALL)的mock调用会出发警告或导致测试失败)。
作用2:
NickMock会为未设置期望的函数提供默认返回值。对于数值类型返回0,对于指针返回nullptr,对于布尔返回false
作用3:
如果某个接口中有很多方法,而我们只关心其中几个,使用 NiceMock 可以避免为每个不关心的方法设置期望,同时还确保测试过程不会因未设置期望的方法调用而失败。
示例:
class MockInterface : public Interface {
public:MOCK_METHOD(int, getnumber, (), (override));MOCK_METHOD(int, dosomething, (), (override));
};
TEST(mockTest, niceMock) {NiceMock<MockInterface> mock_obj;EXPECT_CALL(mock_obj, getnumber).willonce(::testing::Return(42));EXPECT_EQ(mock_obj.getnumber(), 42);mock_obj.dosomething(); 即使dosomething没有设置期望,使用nicemock对象调用时 也不会报错或产生警告。
}
Naggymock:::testing::NaggyMock<T>
在没有明确设置期望的mock方法被调用时发出警告,但不会导致测试失败。
用于帮助开发者检测可能漏掉的期望设置,提醒开发者某个mock方法调用了却没有定义期望行为。但不会导致测试失败,会继续运行,调用没有期望的函数会返回默认值。
StrictMock:::testing::StrictMock<T>
具有严格行为要求的mock对象类型
要求每个mock方法的调用都必须明确设置期望。如果在测试过程中调用了未设置期望的mock方法,StrictMock会立即触发错误并导致测试失败。
Sequence/InSequence
用于控制mock调用顺序的工具。
(1)Sequence:确保mock对象的方法按照特定顺序调用。可以通过EXPECT_CALL为某些方法添加顺序约束,要求他们在特定顺序下执行。
示例:
class mockInterface : public Interface {
public:MOCK_METHOD(int, getnumber, (), (override));MOCK_METHOD(int, dosomething, (), (override));
};
TEST(mockTest, sequenceExample) {mockInterface mock_obj;Sequence s;EXPECT_CALL(mock_obj, getnumber()).InSequence(s).willonce(Return(1));EXPECT_CALL(mock_obj, dosomething().InSequence(s);EXPECT_EQ(mock_obj.getnumber(), 1);mock_obj.dosomething();必须先调用getnumber再调用dosomething
}
(2)InSequence:确保在其生命周期内,所有EXPECT_CALL设置的期望必须按照顺序执行。与Sequence不同,它可以不显示创建Sequence对象,更加简介。
示例:
class mockInterface : public Interface {
public:MOCK_METHOD(int, getnumber, (), (override));MOCK_METHOD(int, dosomething, (), (override));
};
TEST(mockTest, sequenceExample) {mockInterface mock_obj;InSequence seq;EXPECT_CALL(mock_obj, getnumber()).willonce(Return(1));EXPECT_CALL(mock_obj, dosomething();EXPECT_EQ(mock_obj.getnumber(), 1);mock_obj.dosomething();必须先调用getnumber再调用dosomething
}
Expectation/ExpectationSet
用于管理和组织mock方法调用期望的工具。允许定义和控制mock对象的行为,并确保特定的调用顺序或依赖关系
(1)Expectation
通过EXPECT_CALL可以创建一个Expectation对象 Expectation e = EXPECT_CALL(....)
e的作用:
将e传给After()可以指定某些期望,必须在其他期望之后才被调用
(2)ExpectationSet是一个集合容器,允许将多个Expectation对象组合在一起
当我们有多个期望,并且不需要按特定顺序执行时,可以使用ExpectationSet来管理这些期望。ExpectationSet es; es += EXPECT_CALL(); es += EXPECT_CALL()
es的作用:
将es传给After()可以指定某个期望必须在某个集合中的期望都被调用之后才被调用。
Mather(匹配器)
用于定义/限制mock类中的方法的形参的值,如果method不需要形参可以保持match为空
通配符
1. _:匹配任意参数,不关心他的具体值或类型
EXPECT_CALL(mcokObj, method(_, _)).Times(1);
2. A<Type>()和An<Type>():匹配任意类型为Type的参数或对象,A<Type>()用于非引用类型,An<Type>()用于匹配引用类型。
复合匹配器
(1)AnyOf(.....)
如果参数符合其中任意一个条件,则匹配成功,用于参数有多种可能值时,用AngOf匹配多个可能的情况
EXPECT_CALL(mockObj, method(AnyOf(a, b, c....)).Times(1)
(2)AllOf(......)
当参数同时满足多个条件时,匹配成功。用来组合多个匹配器,要求所有匹配器都满足。
EXPECT_CALL(mockObj, method(AllOf(Gt(10), Lt(20))).Times(1)
(3)Not(matcher....)
反转匹配的结果,只有匹配器条件为假时,才会匹配成功
通用匹配器
浮点匹配器
字符串匹配器
mulit-argument matchers多参数匹配器
诸如Eq()、Ge().....等的
以及AllArgs(matcher)和Args<N1,N2, ........, NK>(matcher)
1.AllArgs(matcher)
用于将传递给模拟方法的所有参数作为整体,并将它们传递给另一个匹配器进行匹配。它适用于你想对多个参数一起应用匹配器时的场景。
2.Args<N1,N2, ........, NK>(matcher)
成员匹配器
(1)Filed(&class::field, m)
用于匹配类对象中特定字段的值
struct mystruct {int id;
};
mystruct obj = {5};
EXPECT_THAT(obj, &mystruct::id, 5);
(2)Filed(field_name,&class::field, m)
和第一个类似,但允许使用字段名称字符串表示
EXPECT_THAT(obj, Field(“id”, &mystruct::id, 5));
(3)Key(e)
用于匹配容器中指定键的存在,适用于map或类似数据结构,验证键是否存在。
std::map<std::string,int> mymap = {{“key1”, 1}};
EXPECT_THAT(mymap, Contains(key(“key1”)));
(4)Pain(m1, m2)
用于匹配键值对,常用于map中的元素
用于验证一个特定的键值对是否存在于容器中
EXPECT_THAT(mymap, Contains(Pair(“key1”, 1)));
(5)FieldsAre(m......)
用于同时验证多个字段的值
可传入多个Field、property匹配器,以检查对象的多个属性
EXPECT_THAT(mymap, FieldsAre(Field(&mystruct::id, 5),Field(&mystruct::name, “tests”))))
(6)Property(&class::property, m)
用于验证类中某个成员函数(通常是getter)返回的值。
其中property是某个成员函数的指针,m是期望的返回值
注意:property所代表的函数应该不带参数并且声明为const。
struct mystruct {int getValue() const {return 10;}
};
mystruct obj;
EXPECT_THAT(obj, Property(&mystruct::getvalue,10));
(7)Property(property_name,&class::property, m)
与上一个匹配器类似,允许通过属性名称来描述属性。
EXPECT_THAT(obj, Property(“value”,&mystruct::getvalue,10));
actions(行为)
Return
①ReturnArg<N>():用于在模拟对象的方法被调用时返回传入参数的第 N 个值。
②ReturnNew<T>(args...):用于模拟方法调用时返回一个新分配的对象指针。该对象的类型为 T,并且可以通过传递构造函数参数来初始化这个对象。
其中:
T:指定要创建的对象的类型。
args...:传递给对象构造函数的参数,可以是任意数量和类型的参数。
③ReturnPointee(ptr):用于模拟方法调用时返回指向某个对象的指针,具体来说,它返回指向 ptr 指向的值的指针。
④ReturnRef(variable):
功能:用于模拟方法调用时返回一个变量的引用。
用法:适用于需要返回引用类型的函数,可以直接返回一个现有变量的引用。
⑤ReturnRoundRobin({a1, ..., ak})
功能:用于模拟方法调用时按顺序返回给定列表中的值,返回值会循环使用。
用法:适合需要多次调用返回不同值的场景。
side effects
Invoke
①f:传给模拟函数的参数可调用对象,f可以是任何可调用的对象,如普通函数、lambda或functor
②Invoke(f):
③Invoke(object_pointer, &class::method)
④InvokeWithoutArgs(f)
调用不带参数的全局或静态函数f
⑤InvokeWithoutArgs(object_pointer, &class::method)
调用指定对象的无参数成员函数
Default Action
在设置期望时如果没有为特定的函数调用指定其他行为,调用DoDefault()可以确保模拟对象按照正常的、未被覆盖的方式执行。
Composite Actions
①DoAll(a1,a2,.......) :依次执行所有提供的子动作,a1到an,并在每次调用时返回最后一个动作的结果。前n-1个动做必须返回void,并且前n-1个动作可以读取传递给模拟的函数的参数,但不能修改他们。最后一个子动作可以读取或者修改传递给模拟函数的参数。
②IgnoreResult(a)
执行动作 a,但忽略其返回值。a 不能是一个返回 void 的函数。
.willonce(::testing::IgnoreResult(a))
③withArgs<N>(a)
将模拟函数的第N个参数传递给动作a并执行该动作。
④withArgs<N1,N2,......>(a)
将模拟函数的多个参数传递给动作a并执行该动作。
注意:其中x和y就是传递给somemethod的第一二个参数
⑤withoutArgs(a)
执行动作a,不做任何操作
基数(cardinalities)
用于timer()中来指定模拟函数将被调用多少次