2.1 如何测试对象方法
MockCpp支持面向接口的测试,如以下接口类:
class ICalc
{
public:
virtual ~ICalc() {};
virtual int add(int a, int b) = 0;
};
add接口测试用例:
TEST_F(CalcTest, should_return_11_after_mock_ICalc_add_method)
{
MockObject calc;
MOCK_METHOD(calc, add)
.stubs()
.will(returnValue(11));
EXPECT_EQ(11, calc->add(1,1));
}
2.2 让同一个方法返回不同的值
TEST_F(CalcTest, should_return_different_value_when_mock_return_value)
{
MockObject calc;
MOCK_METHOD(calc, add)
.stubs()
.will(returnValue(10))
.then(repeat(20,2))
.then(returnValue(5));
EXPECT_EQ(10, calc->add(1,1));
EXPECT_EQ(20, calc->add(1,1));
EXPECT_EQ(20, calc->add(1,1));
EXPECT_EQ(5, calc->add(1,1));
}
2.3 根据不同的函数入参控制返回值
TEST_F(CalcTest, should_return_different_values_when_given_exact_params)
{
MockObject calc;
MOCK_METHOD(calc, add)
.stubs()
.with(eq(1), eq(1))
.will(returnValue(11));
MOCK_METHOD(calc, add)
.stubs()
.with(eq(2), any())
.will(returnValue(21));
EXPECT_EQ(11, calc->add(1,1));
EXPECT_EQ(21, calc->add(2,5));
}
2.4 不同的用例中使用同一个变量
struct CalcTest : public ::testing::Test {
virtual void SetUp() {
digital_ = 2;
}
virtual void TearDown() {
digital_ = 0;
GlobalMockObject::verify();
}
int digital_;
};
TEST_F(CalcTest, should_return_10_when_5_multi_2) {
EXPECT_EQ(10, multi(digital_, 5));
}
TEST_F(CalcTest, should_return_15_when_5_multi_3) {
digital_ = 3;
EXPECT_EQ(15, multi(digital_, 5));
}
TEST_F(CalcTest, the_value_of_digital_should_recover_to_2) {
EXPECT_EQ(2, digital_);
}
2.5 函数中有条件分支,并且调用了其他函数,怎么测
int proc(int value) {
int ret = 0;
if (2 == apiOtherModule()) { //其它模块的接口,不知如何修改其值
ret = divi(value, 2);
}
else {
ret = multi(value, 3);
}
return multi(ret, 2);
}
TEST_F(CalcTest, should_return_8) {
MOCKER(apiOtherModule).stubs().will(returnValue(2));
EXPECT_EQ(8, proc(8));
}
TEST_F(CalcTest, should_return_2) {
MOCKER(apiOtherModule).stubs().will(returnValue(6));
MOCKER(multi).will(returnValue(2));
EXPECT_EQ(2, proc(8));
}
2.6 流程式的函数怎么测
proc中,根据外部接口返回值的不同,进行了不同流程的处理,并且返回值类型为void:
void proc() {
if (1 == apiOtherModule ()) {
proc1();
}
else if (2 == apiOtherModule ()) {
proc2();
}
else {
return;
}
return proc2();
}
可以使用以下三个测试用例来针对流程进行测试:
TEST_F(CalcTest, description_1) {
MOCKER(apiOtherModule)
.stubs().will(returnValue(1));
MOCKER(proc1)
.expects(once())
.will(returnValue(0));
MOCKER(proc2)
.expects(once())
.will(returnValue(0));
proc();
}
TEST_F(CalcTest, description_2) {
MOCKER(apiOtherModule)
.stubs().will(returnValue(2));
MOCKER(proc1)
.expects(never())
.will(returnValue(0));
MOCKER(proc2)
.expects(atLeast(2))
.will(returnValue(0));
proc();
}
TEST_F(CalcTest, description_3) {
MOCKER(apiOtherModule)
.stubs().will(returnValue(5));
MOCKER(proc1)
.expects(never())
.will(returnValue(0));
MOCKER(proc2)
.expects(never())
.will(returnValue(0));
proc();
}
如果不同分支下,调用的函数相同,只是顺序不一样呢?下面的proc函数,不同的分支都调用了proc1和proc2函数,只是调用的顺序不一样:
void proc() {
if (1 == apiOtherModule()) {
proc1();
proc2();
}
else {
proc2();
proc1();
}
return;
}
可以使用下面的两个用例进行测试:
TEST_F(CalcTest, description_4) {
MOCKER(apiOtherModule)
.stubs().will(returnValue(1));
MOCKER(proc1)
.expects(once())
.will(returnValue(0))
.id("proc1");
MOCKER(proc2)
.expects(once())
.after("proc1")
.will(returnValue(0));
proc();
}
TEST_F(CalcTest, description_5) {
MOCKER(apiOtherModule)
.stubs().will(returnValue(3));
MOCKER(proc1)
.expects(once())
.will(returnValue(0))
.id("proc1");
MOCKER(proc2)
.expects(once())
.before("proc1")
.will(returnValue(0));
proc();
}
2.7 MockCpp的错误提示信息
MockCpp有详细的错误提示信息,指明具体的错误原因,帮助开发者迅速定位问题:
[ RUN ] CalcTest.should_invoke_proc1_once_proc2
e:\svn\\tools\include\mockcpp\chainablemockmethod.h(69): error:
Expected invoked before the invocation with id "proc1", but that invocation has been invoked.
method(proc2)
.expects(once())
.invoked(1)
.before(, "proc1")
.will(returnValue((int)0/0));
unknown file: error: C++ exception with description "failed due to mockcpp exception" thrown in the test body.
[ FAILED ] CalcTest.should_invoke_proc1_once_proc2 (0 ms)