Skip to content

Commit 18b6baf

Browse files
committed
add the example for mock/fake ggtest
1 parent 050cea6 commit 18b6baf

9 files changed

Lines changed: 245 additions & 2 deletions

File tree

‎CMakeLists.txt‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ set(PROJECT_NAME_TEST ${PROJECT_NAME}_unit_test) # name for the unit-test execut
2424
# ----------------------------------------------------------------------------------------
2525
# Compiler and language configuration
2626
# ----------------------------------------------------------------------------------------
27-
# Require C++17 for GoogleTest and modern C++ features
27+
# Require at least C++17 for GoogleTest and modern C++ features
2828
set(CMAKE_CXX_STANDARD 20)
2929
set(CMAKE_CXX_STANDARD_REQUIRED ON)
3030

@@ -176,9 +176,10 @@ target_include_directories(${PROJECT_NAME_TEST}
176176
PRIVATE ${APP_HEADERS} # PRIVATE for internal use within a target,
177177
)
178178

179-
# Link GoogleTest to the test executable
179+
# Link GoogleTest, GoogleMock to the test executable
180180
target_link_libraries(${PROJECT_NAME_TEST}
181181
GTest::gtest_main
182+
GTest::gmock_main
182183
)
183184

184185
# Register tests with CTest

‎src/leetcode/arrays/3sum/Solution.cpp‎

Whitespace-only changes.

‎src/leetcode/arrays/3sum/Solution.h‎

Whitespace-only changes.

‎tests/DeleteMeTest.cpp‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,47 @@ TEST(DivTest, FailureMessage) {
5252
// ASSERT_FALSE(true) << "FailureMessage: ASSERT_FALSE(true)";
5353
}
5454

55+
#include <gmock/gmock.h>
56+
#include "mock/MockTurtle.h"
57+
#include "mock/Painter.h"
58+
TEST(MockPainterTest, DrawSquare_CallsCorrectTurtleOperations) {
59+
MockTurtle turtle;
60+
Painter painter{turtle};
61+
62+
EXPECT_CALL(turtle, PenDown()).Times(1);
63+
64+
EXPECT_CALL(turtle, Forward(100)).Times(4);
65+
EXPECT_CALL(turtle, Turn(90)).Times(4);
66+
67+
EXPECT_CALL(turtle, PenUp()).Times(1);
68+
69+
painter.DrawSquare(100);
70+
}
71+
72+
#include "mock/FakeTurtle.h"
73+
TEST(FakePainterTest, DrawSquare_ProducesSquarePath) {
74+
FakeTurtle turtle;
75+
Painter painter{turtle};
76+
77+
painter.DrawSquare(10);
78+
79+
const auto& path = turtle.Path();
80+
81+
ASSERT_EQ(path.size(), 8); // 4 lines → 8 points (start/end)
82+
83+
EXPECT_EQ(path[0], std::make_pair(0, 0));
84+
EXPECT_EQ(path[1], std::make_pair(0, 10));
85+
86+
EXPECT_EQ(path[2], std::make_pair(0, 10));
87+
EXPECT_EQ(path[3], std::make_pair(10, 10));
88+
89+
EXPECT_EQ(path[4], std::make_pair(10, 10));
90+
EXPECT_EQ(path[5], std::make_pair(10, 0));
91+
92+
EXPECT_EQ(path[6], std::make_pair(10, 0));
93+
EXPECT_EQ(path[7], std::make_pair(0, 0));
94+
}
95+
5596
int main(int argc, char** argv) {
5697
testing::InitGoogleTest(&argc, argv);
5798
return RUN_ALL_TESTS();

‎tests/README.md‎

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# GoogleTest
2+
- GoogleTest helps you write better C++ tests.
3+
## 1. Basic Concepts
4+
- **assertions:** the statememts that check whether a condition is true. The result can be:
5+
- success
6+
- nonfatal failure
7+
- fatal failure
8+
- **test suite:** that contains one or many tests.
9+
- **text fixture:** the class contain test suite used for multiple tests to share common objects and subroutines.
10+
11+
## 2. Test Fixtures: Using the Same Data Configuration for Multiple Tests
12+
- To create a fixture class:
13+
- derive a class from `testing::Test` with protected body
14+
- declare used objects
15+
- write a default constructor or `Setup()` function to prepare the object for each test.
16+
- write a default destructor or `TearDown()` function to release resources.
17+
- use `TEST_F(TestFixtureClassName, TestName)` instead of `TEST()`
18+
19+
- e.g.
20+
```cpp
21+
#include "this/package/foo.h"
22+
23+
#include <gtest/gtest.h>
24+
25+
namespace my {
26+
namespace project {
27+
namespace {
28+
29+
// The fixture for testing class Foo.
30+
class FooTest : public testing::Test {
31+
protected:
32+
// You can remove any or all of the following functions if their bodies would
33+
// be empty.
34+
35+
FooTest() {
36+
// You can do set-up work for each test here.
37+
}
38+
39+
~FooTest() override {
40+
// You can do clean-up work that doesn't throw exceptions here.
41+
}
42+
43+
// If the constructor and destructor are not enough for setting up
44+
// and cleaning up each test, you can define the following methods:
45+
46+
void SetUp() override {
47+
// Code here will be called immediately after the constructor (right
48+
// before each test).
49+
}
50+
51+
void TearDown() override {
52+
// Code here will be called immediately after each test (right
53+
// before the destructor).
54+
}
55+
56+
// Class members declared here can be used by all tests in the test suite
57+
// for Foo.
58+
};
59+
60+
// Tests that the Foo::Bar() method does Abc.
61+
TEST_F(FooTest, MethodBarDoesAbc) {
62+
const std::string input_filepath = "this/package/testdata/myinputfile.dat";
63+
const std::string output_filepath = "this/package/testdata/myoutputfile.dat";
64+
Foo f;
65+
EXPECT_EQ(f.Bar(input_filepath, output_filepath), 0);
66+
}
67+
68+
// Tests that Foo does Xyz.
69+
TEST_F(FooTest, DoesXyz) {
70+
// Exercises the Xyz feature of Foo.
71+
}
72+
73+
} // namespace
74+
} // namespace project
75+
} // namespace my
76+
77+
int main(int argc, char **argv) {
78+
testing::InitGoogleTest(&argc, argv);
79+
return RUN_ALL_TESTS();
80+
}
81+
```
82+
83+
## 3. gMock
84+
- It's not feasible or wide to rely on real objects entirely when testing.
85+
- A mocks object implements the same interface as a real object, but lets you specify at run time how it will be used and what it should do (which methods will be called? in which order? how many times? with what arguments? what will they return? etc).
86+
- `Fake objects` vs `Mock objects`:
87+
- Fake objects have working implementations, but usually take some shortcut. e.g. return a static or in-memory value instead of the actual computation.“what happened?”
88+
89+
- Mock objects are objects pre-programmed with expectations, which form a specification of the calls they are expected to receive. “how did it happen?”
90+
91+
- **gMock** is a library (sometimes we also call it a “framework” to make it sound cool) for creating mock classes and using them. It does to C++ what jMock/EasyMock does to Java (well, more or less).
92+
93+
>When using gMock,
94+
+) first, you use some simple macros to describe the interface you want to mock, and they will expand to the implementation of your mock class;
95+
+) next, you create some mock objects and specify its expectations and behavior using an intuitive syntax;
96+
+) then you exercise code that uses the mock objects. gMock will catch any violation to the expectations as soon as it arises.
97+
TBD https://google.github.io/googletest/gmock_for_dummies.html

‎tests/mock/FakeTurtle.h‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#pragma once
2+
3+
#include <utility>
4+
#include <vector>
5+
#include "Turtle.h"
6+
7+
class FakeTurtle : public Turtle {
8+
public:
9+
FakeTurtle() = default;
10+
11+
void PenUp() override { penDown_ = false; }
12+
13+
void PenDown() override { penDown_ = true; }
14+
15+
void Forward(int distance) override {
16+
if (penDown_) {
17+
path_.emplace_back(x_, y_);
18+
}
19+
20+
switch (direction_) {
21+
case 0:
22+
y_ += distance;
23+
break; // north
24+
case 90:
25+
x_ += distance;
26+
break; // east
27+
case 180:
28+
y_ -= distance;
29+
break; // south
30+
case 270:
31+
x_ -= distance;
32+
break; // west
33+
}
34+
35+
if (penDown_) {
36+
path_.emplace_back(x_, y_);
37+
}
38+
}
39+
40+
void Turn(int degrees) override { direction_ = (direction_ + degrees) % 360; }
41+
42+
void GoTo(int x, int y) override {
43+
x_ = x;
44+
y_ = y;
45+
}
46+
47+
int GetX() const override { return x_; }
48+
int GetY() const override { return y_; }
49+
50+
const std::vector<std::pair<int, int>>& Path() const { return path_; }
51+
52+
private:
53+
int x_{0};
54+
int y_{0};
55+
int direction_{0}; // 0=north, 90=east, ...
56+
bool penDown_{false};
57+
58+
std::vector<std::pair<int, int>> path_;
59+
};

‎tests/mock/MockTurtle.h‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include "Turtle.h" // mock test for this class
2+
#include <gmock/gmock.h> // Brings in gMock.
3+
4+
class MockTurtle : public Turtle {
5+
public:
6+
MOCK_METHOD(void, PenUp, (), (override)); // the MOCK_METHOD macro will generate the definitions for APIs
7+
MOCK_METHOD(void, PenDown, (), (override));
8+
MOCK_METHOD(void, Forward, (int distance), (override));
9+
MOCK_METHOD(void, Turn, (int degrees), (override));
10+
MOCK_METHOD(void, GoTo, (int x, int y), (override));
11+
MOCK_METHOD(int, GetX, (), (const, override));
12+
MOCK_METHOD(int, GetY, (), (const, override));
13+
};

‎tests/mock/Painter.h‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
#include "Turtle.h"
3+
4+
class Painter {
5+
public:
6+
explicit Painter(Turtle& turtle) : turtle_(turtle) {}
7+
8+
void DrawSquare(int size) {
9+
turtle_.PenDown();
10+
for (int i = 0; i < 4; ++i) {
11+
turtle_.Forward(size);
12+
turtle_.Turn(90);
13+
}
14+
turtle_.PenUp();
15+
}
16+
17+
private:
18+
Turtle& turtle_;
19+
};

‎tests/mock/Turtle.h‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
class Turtle {
4+
public:
5+
virtual ~Turtle() {}
6+
virtual void PenUp() = 0;
7+
virtual void PenDown() = 0;
8+
virtual void Forward(int distance) = 0;
9+
virtual void Turn(int degrees) = 0;
10+
virtual void GoTo(int x, int y) = 0;
11+
virtual int GetX() const = 0;
12+
virtual int GetY() const = 0;
13+
};

0 commit comments

Comments
 (0)