Welcome to our third lesson on Test-Driven Development (TDD) with Test Doubles in C++. In this lesson, we focus on Spies, an essential test double type used to observe interactions with your code's dependencies during testing. By now, you've already been introduced to Dummies and Stubs in previous lessons, allowing you to manage dependencies via test doubles effectively.
Our goal here is to seamlessly integrate Spies into the TDD Red-Green-Refactor cycle: writing tests (Red), creating a minimal implementation (Green), and refactoring for better quality without altering behavior. Let's dive into understanding and using Spies within this framework!
Spies in Google Mock allow you to observe and record how functions in your application are used without modifying their behavior. In TDD, Spies help verify that functions are called when and how you expect them to be, which is a vital part of writing reliable tests.
With Spies in Google Mock, you can verify:
- If a method was called
- How many times it was called
- With what arguments it was called
Spies align perfectly with the Red-Green-Refactor cycle:
- Red: Write a failing test to ensure your code's behavior is verified.
- Green: Implement only enough code for the tests to pass.
- Refactor: Clean up the tests and the implementation for better software design.
Let's move on to setting up our environment, utilizing the powerful features of Google Mock.
Let's consider a Notification Service example where we aim to ensure notifications are sent with appropriate priorities. We will begin by implementing a Spy on the Send
method of the RealNotificationSender
using Google Mock.
Here's an example setup:
- We define a
RealNotificationSender
class with a virtualSend
method. - We create a
MockNotificationSender
that inherits fromRealNotificationSender
and implements theSend
method using Google Mock'sMOCK_METHOD
macro. - The
NotificationService
class uses aRealNotificationSender
(or any subclass) to send notifications. - This Spy will help us verify interactions with the
Send
method.
Next, we insert failing tests to see our Spies in action. Remember that writing failing tests is our "Red" step in TDD.
Let's add a test case to observe the behavior of the Send
method using our Google Mock Spy.
- We create a test to ensure our notification sends with the correct priority.
- The
EXPECT_CALL
method sets up expectations for theSend
method's behavior. Times(1)
verifies that the method is called exactly once with the specified parameters.
In a TDD approach, we would first write this test before implementing the NotifyUser
method. The test would initially fail, representing the Red phase of our TDD cycle.
Google Mock's verification tools allow you to assert that specific interactions occurred during a test. The fundamental mechanism is the EXPECT_CALL
macro:
This statement has two main parts:
- The method and parameters we expect to be called
- The verification of how many times it should be called
When your test runs, Google Mock automatically checks if the method was called with the exact parameters specified. If not, the test will fail with a detailed message.
You can specify the expected number of calls in various ways:
Instead of requiring exact parameter matches, you can use matchers for more flexible verification:
For complex objects as parameters, the testing::Field
matcher lets you verify specific properties:
This allows for precise verification of object properties without matching the entire object.
In a true TDD workflow, we would write the test before implementing any functionality. After writing the failing test to verify how our Send
method should be called, the next step is to implement the minimal functionality required to make the test pass.
Here's the implementation of the NotifyUser
method that would make our test pass:
- The
NotifyUser
method callsSend
with the provideduserId
,message
, and a priority of 1. - This is the minimal amount of code necessary to get the test to pass.
With this implementation, running the test will pass, taking us from the Red to the Green phase of TDD.
In this lesson, we've explored the importance of Spies as test doubles in the TDD process using C++, Google Test, and Google Mock. Here's what we've achieved:
- Red: Set up tests simulating real-world scenarios, initially leading them to fail.
- Green: We strategized to write the least amount of functionality to fulfill all test criteria.
- Refactor: Ensured our code and tests remain clean, scalable, and comprehensible.
As we transition into practice exercises, focus on implementing Spies in different scenarios to solidify these concepts. The exercises will guide you in writing, verifying, and refactoring tests with Spies, empowering you to integrate this knowledge into complex projects.
Happy testing and enjoy the lessons you've built through TDD in C++ with Google Test and Google Mock!
