## GMOCK * Avoid depricated MOCK_METHDn and MOCK_CONST_METHODn * Use MOCK_METHOD() * Use Times when want to expect how many times function was call (by default it expect once) * Use AtLeast To expect n or more calls * Use WillOnce and WillRepeatedly to perform some actions * Use SaveArg to save argument provided to mock function * Use InSequence to perform sequenced actions * You can mock non-virtual function * Use StrictMock when you need to be sure about every call of this mock * Use NiceMock when you don't care about function called for this mock * Use ON_CALL and WillByDefault to perform some default action, when function will be called * Use DoAll to perform more then one action * Use Invoke to invoke funtion/lambda ___ ## MOCK_METHOD MOCK_METHOD(return_type, name_of_function, arguments, parameters) ```C++ class MockTurtle : public Turtle { public: ... MOCK_METHOD(void, PenUp, (), (override)); MOCK_METHOD(void, PenDown, (), (override)); MOCK_METHOD(void, Forward, (int distance), (override)); MOCK_METHOD(void, Turn, (int degrees), (override)); MOCK_METHOD(void, GoTo, (int x, int y), (override)); MOCK_METHOD(int, GetX, (), (const, override)); MOCK_METHOD(int, GetY, (), (const, override)); }; ``` * const - Makes the mocked method a const method. Required if overriding a const method. * override - Marks the method with override. Recommended if overriding a virtual method. * noexcept - Marks the method with noexcept. Required if overriding a noexcept method. * Calltype(...) - Sets the call type for the method (e.g. to STDMETHODCALLTYPE), useful in Windows. * ref(...) - Marks the method with the reference qualification specified. Required if overriding a method that has reference qualifications. Eg ref(&) or ref(&&). ___ ## Test class Let's use once agin `Foo` and `Bar` class ```C++ class Bar { public: virtual ~Bar() = default; virtual bool doOtherStuff(const std::string& str, int*, const std::vector& vec) const { // do some stuff return false; } }; class MockBar : public Bar { public: ~MockBar() override = default; MOCK_METHOD(bool, doOtherStuff, (const std::string&, int*, const std::vector&), (const override)); }; class Foo { public: Foo(std::unique_ptr bar) : val_(std::make_unique(42)), bar_(std::move(bar)) {} bool doSth(const std::string& str) { return bar_->doOtherStuff(str, val_.get(), {1, 2, 3, 4}); } private: std::unique_ptr val_; std::unique_ptr bar_; }; ``` ___ ## Times ```C++ TEST(ExampleTest, ShouldTest) { auto mockBar = std::make_unique(); auto* mockBarPtr = mockBar.get(); Foo foo(std::move(mockBar)); EXPECT_CALL(*mockBarPtr, doOtherStuff).Times(2); foo.doSth("Sth1"); foo.doSth("Sth2"); } ``` ___ ## AtLeast ```C++ TEST(ExampleTest, ShouldTest) { auto mockBar = std::make_unique(); auto* mockBarPtr = mockBar.get(); Foo foo(std::move(mockBar)); EXPECT_CALL(*mockBarPtr, doOtherStuff).Times(testing::AtLeast(2)); foo.doSth("Sth1"); foo.doSth("Sth2"); } ``` ___ ## WillOnce and WillRepeatedly ```C++ TEST(ExampleTest, ShouldTest) { auto mockBar = std::make_unique(); auto* mockBarPtr = mockBar.get(); Foo foo(std::move(mockBar)); // Dont do that. Next exceptaion will override first one! // EXPECT_CALL(*mockBarPtr, doOtherStuff).WillOnce(Return(false)); // EXPECT_CALL(*mockBarPtr, doOtherStuff).WillOnce(Return(true)); // Correct one! EXPECT_CALL(*mockBarPtr, doOtherStuff) .WillOnce(Return(false)) .WillOnce(Return(true)); EXPECT_FALSE(foo.doSth("Sth1")); EXPECT_TRUE(foo.doSth("Sth2")); } ``` ```C++ TEST(ExampleTest, ShouldTest) { //... EXPECT_CALL(*mockBarPtr, doOtherStuff) .WillOnce(Return(false)) .WillOnce(Return(true)) .WillRepeatedly(Return(false)); EXPECT_FALSE(foo.doSth("Sth1")); EXPECT_TRUE(foo.doSth("Sth2")); EXPECT_FALSE(foo.doSth("Sth3")); EXPECT_FALSE(foo.doSth("Sth4")); } ``` ___ ## Save arguments provided to functions (1) We want to capture parameters provided to bar function. ```C++ class Bar { public: virtual ~Bar() = default; virtual bool doOtherStuff(const std::string& str, int val, const std::vector& vec) { // do some stuff return false; } }; class MockBar : public Bar { public: ~MockBar() override = default; MOCK_METHOD(bool, doOtherStuff, (const std::string&, int, const std::vector&), (override)); }; class Foo { public: Foo(std::unique_ptr bar) : bar_(std::move(bar)) {} bool doSth(const std::string& str) { return bar_->doOtherStuff(str, 42, {1, 2, 3, 4}); } private: std::unique_ptr bar_; }; ``` ___ ## Save arguments provided to functions (2) ```C++ TEST(ExampleTest, ShouldTest) { auto mockBar = std::make_unique(); auto* mockBarPtr = mockBar.get(); Foo foo(std::move(mockBar)); int val; std::vector vec; // Also return true, instead of false like in original function EXPECT_CALL(*mockBarPtr, doOtherStuff). WillOnce(DoAll(SaveArg<1>(&val), SaveArg<2>(&vec), Return(true))); EXPECT_TRUE(foo.doSth("Sth")); EXPECT_EQ(val, 42); const auto expected = std::vector{1, 2, 3, 4}; EXPECT_EQ(vec, expected); } ``` ``` [----------] 1 test from ExampleTest [ RUN ] ExampleTest.ShouldTest [ OK ] ExampleTest.ShouldTest (0 ms) [----------] 1 test from ExampleTest (0 ms total) ``` ___ ## Save pointer provided to function ```C++ class Bar { public: virtual ~Bar() = default; virtual bool doOtherStuff(const std::string& str, int* val, const std::vector& vec) { // do some stuff return false; } }; ``` ```C++ TEST(ExampleTest, ShouldTest) { auto mockBar = std::make_unique(); auto* mockBarPtr = mockBar.get(); Foo foo(std::move(mockBar)); int* val; std::vector vec; // Capture by SaveArgPointee EXPECT_CALL(*mockBarPtr, doOtherStuff). WillOnce(DoAll(SaveArgPointee<1>(val), SaveArg<2>(&vec), Return(true))); EXPECT_TRUE(foo.doSth("Sth")); EXPECT_EQ(*val, 42); const auto expected = std::vector{1, 2, 3, 4}; EXPECT_EQ(vec, expected); } ``` ___ ## Capture non-copyable object * There is a problem to capture non-copyable objects because we can't copy them! * We need to make an ugly hack to capture this object -> move this object to our variable. * This will be problematic when this object needs to be used in a function, but it will work when we used in on mock function because the argument will not be used later. ```C++ // Bar bool doSth(const std::string& str) { return bar_->doOtherStuff(str, std::make_unique(42), {1, 2, 3, 4}); } TEST(ExampleTest, ShouldTest) { auto mockBar = std::make_unique(); auto* mockBarPtr = mockBar.get(); Foo foo(std::move(mockBar)); std::unique_ptr val; EXPECT_CALL(*mockBarPtr, doOtherStuff).WillOnce(DoAll(MoveObject<1>(&val), Return(true))); EXPECT_TRUE(foo.doSth("Sth")); EXPECT_EQ(*val, 42); } ``` * There is no such function in gtest, so we need to implement somehow MoveObject ___ ## Move object ```C++ ACTION_TEMPLATE(MoveObject, HAS_1_TEMPLATE_PARAMS(int, k), AND_1_VALUE_PARAMS(pointer)) { using PtrType = std::remove_cv_t(args))>>; // This unique_ptr will be deleted after function end // so we need to capture it *pointer = std::move(const_cast(std::get(args))); } ``` When we only need a raw pointer from `unique_ptr` ```C++ ACTION_TEMPLATE(ExtractPtr, HAS_1_TEMPLATE_PARAMS(int, k), AND_1_VALUE_PARAMS(pointer)) { *pointer = std::get(args).get(); } ``` But we will lost it, because `unique_ptr` will be deleted after exit form mock function! This is a very old way, the better one is to just lambda instead, I will show this later ___ ## InSequence (1) ```C++ TEST(ExampleTest, ShouldTest) { auto mockBar = std::make_unique(); auto* mockBarPtr = mockBar.get(); Foo foo(std::move(mockBar)); testing::Sequence seq; // Four expectations in sequence. There is no override like before for (int i = 0; i < 4; ++i) { EXPECT_CALL(*mockBarPtr, doOtherStuff) .InSequence(seq) .WillOnce(Return(i % 2)); } EXPECT_FALSE(foo.doSth("Sth1")); EXPECT_TRUE(foo.doSth("Sth2")); EXPECT_FALSE(foo.doSth("Sth3")); EXPECT_TRUE(foo.doSth("Sth4")); } ``` ___ ## InSequence (2) This has the same behaviour like previous example ```C++ TEST(ExampleTest, ShouldTest) { auto mockBar = std::make_unique(); auto* mockBarPtr = mockBar.get(); Foo foo(std::move(mockBar)); { testing::InSequence seq; // Four expectations in sequence. There is no override like before for (int i = 0; i < 4; ++i) { EXPECT_CALL(*mockBarPtr, doOtherStuff).WillOnce(Return(i % 2)); } } EXPECT_FALSE(foo.doSth("Sth1")); EXPECT_TRUE(foo.doSth("Sth2")); EXPECT_FALSE(foo.doSth("Sth3")); EXPECT_TRUE(foo.doSth("Sth4")); } ``` ___ ## InSequence - branch out ```C++ testing::Sequence s1, s2; EXPECT_CALL(foo, Method1()) .InSequence(s1, s2); EXPECT_CALL(bar, Method2()) .InSequence(s1); EXPECT_CALL(bar, Method3()) .InSequence(s2); EXPECT_CALL(foo, Method4()) .InSequence(s2); ``` ```C++ +---> Method2 (seq1) (seq1 seq2) | Method1----| | +---> Method3 ---> Method4 (seq2) ``` ___ ## mock non-virtual function (1) We have the following class ```C++ struct Packet {}; class ConcretePacketStream { public: void AppendPacket(Packet* new_packet) {} const Packet* GetPacket(size_t packet_number) const {} size_t NumberOfPackets() const {} }; ``` ___ ## mock non-virtual function (2) We can create mock and instead of dynamic polymorphism use static polymorphism (templates) ```C++ // A mock packet stream class. It inherits from no other, but defines // GetPacket() and NumberOfPackets(). No need to add all functions like: AppendPacket class MockPacketStream { public: // Do not add override! MOCK_METHOD(const Packet*, GetPacket, (size_t packet_number), (const)); MOCK_METHOD(size_t, NumberOfPackets, (), (const)); }; // Now we can use static polymorphism to insert Mock class in a test, // and real class in production code template class PacketReader { public: const Packet* ReadPackets(PacketStream* stream, size_t packet_num) { return stream->GetPacket(packet_num); } }; ``` ___ ## mock non-virtual function (3) Now in test we can use mock class ```C++ TEST(TestNonVirtualMethod, ShouldTest) { MockPacketStream mock_stream; EXPECT_CALL(mock_stream, GetPacket).WillOnce(Return(nullptr)); PacketReader reader; reader.ReadPackets(&mock_stream, 12); } ``` And in production code the real one ```C++ ConcretePacketStream stream; PacketReader reader; auto* packet = reader.ReadPackets(&stream, 12); ``` ___ ## StrictMock The usage of `StrictMock` is similar to normal mock, except that it makes all uninteresting calls failures: ```C++ class MockFoo : public Foo { //... MOCK_METHOD(void, Fun1, (), (override)); MOCK_METHOD(void, Fun2, (), (override)); }; TEST(SimpleTest, TestSth) { StrictMock mock_foo; // When Fun2 will be also called it cause test failed EXPECT_CALL(mock_foo, Fun1()); } ``` ___ ## NiceMock * The usage of `StrictMock` is similar to normal mock, except that it reject uninteresting calls (we will not see them while run test) * NiceMock and StrictMock only affects uninteresting calls (calls of methods with no expectations); they do not affect unexpected calls (calls of methods with expectations, but they don’t match) ```C++ class MockFoo : public Foo { //... MOCK_METHOD(void, Fun1, (), (override)); MOCK_METHOD(void, Fun2, (), (override)); }; TEST(SimpleTest, TestSth) { NiceMock mock_foo; // When Fun2 will be also called it will be ignored EXPECT_CALL(mock_foo, Fun1()); } ``` ___ ## ON_CALL and WillByDefault We can do whatever we want when some mock method will be called. We can even save all types of arguments, or move objects to test them (call later). When a function takes for instance non-copyable callback, and we need to capture it to continue testing, we can move it inside lambda! This is much better than the tricky template shown before. ```C++ TEST(ExampleTest, ShouldTest) { auto mockBar = std::make_unique(); auto* mockBarPtr = mockBar.get(); Foo foo(std::move(mockBar)); // Nice way to capture all types of argument int* ptr; ON_CALL(*mockBarPtr, doOtherStuff) .WillByDefault([&ptr](const std::string&, int* new_ptr, const std::vector&) { ptr = new_ptr; return true; }); EXPECT_CALL(*mockBarPtr, doOtherStuff); EXPECT_TRUE(foo.doSth("Sth1")); EXPECT_EQ(*ptr, 42); } ``` ___ ## DoAll If we need to combine a few actions, we can do this inside `doAll(...)` ```C++ TEST(ExampleTest, ShouldTest) { auto mockBar = std::make_unique(); auto* mockBarPtr = mockBar.get(); Foo foo(std::move(mockBar)); std::string str; int* ptr; EXPECT_CALL(*mockBarPtr, doOtherStuff) .WillOnce(DoAll( SaveArg<0>(&str), SetArgPointee<1>(80), // Replace pointer value SaveArgPointee<1>(ptr), // Capture value of arg1 Return(true))); EXPECT_TRUE(foo.doSth("Sth1")); EXPECT_EQ(str, "Sth1"); EXPECT_EQ(*ptr, 80); } ``` ___ ## Invoke (1) Let's change a little `MockBar` ```C++ class MockBar : public Bar { public: ~MockBar() override = default; MOCK_METHOD(bool, doOtherStuff, (const std::string&, int*, std::function), (const override)); }; ``` Now we want to run callback. We can do this without capture it! ```C++ EXPECT_CALL(*mockBarPtr, doOtherStuff) .WillOnce(DoAll( SaveArg<0>(&str), SetArgPointee<1>(80), // Replace pointer value SaveArgPointee<1>(ptr), // Capture value of arg1 InvokeArgument<2>(500), // Invoke callback Return(true))); ``` ___ ## Invoke (2) ```C++ class Helper { public: void validateArguments(const std::string& str, int* ptr, std::function callback) { ASSERT_EQ(str.size(), 4); EXPECT_EQ(str, "Sth1"); ASSERT_TRUE(ptr); EXPECT_EQ(*ptr, 42); ASSERT_TRUE(callback); callback(50); // We can invoke callback here } }; TEST(ExampleTest, ShouldTest) { auto mockBar = std::make_unique(); auto* mockBarPtr = mockBar.get(); Foo foo(std::move(mockBar)); Helper helper; EXPECT_CALL(*mockBarPtr, doOtherStuff) .WillOnce(DoAll( Invoke(&helper, &Helper::validateArguments), Return(true))); EXPECT_TRUE(foo.doSth("Sth1")); } ``` ___ ## Exercise 2 Open project **SHM** and write test for class `Store.cpp` which will test it's interface. You need to mock `Cargo` class and check if you get correct result based on what you mock. Write mock in `Presentation/exercises/SHM/tests/CargoMock.h` for `Cargo` class. Go to `Presentation/exercises/SHM/build/test` and run test using command `./SHM_Tests`.