C++ Mocking Tips and Tricks for Easier Unit Testing

C++ unit testing has some known issues (you can check them here) but there are also tricks and tips you can use to avoid them and to do unit testing more easily.

In this post blog, we’ll show you seven examples (out of thirteen) that can make your unit testing painless. In order to do that you need to use a good mocking solution to help you unit tests. You can download our mocking solution HERE.

1) TIMES_CALLED Macro:
In the next example, we count the number of times the method “SetCountry” was called.
First, we instantiate an object of type Person and a pointer to an object of type Address. We fake pAddress, and call “SetAddressCountry” 3 times.

The “SetCountry” method belongs to ‘class Address’ and is called inside the “SetAddressCountry” method that belongs to ‘class Person’.
Therefore, the method “SetCountry” should be called 3 times.

Next, we use the TIMES_CALLED macro from our API, which receives the call to the method (“SetCountry”) from the faked object and returns the number of times “SetCountry” was called to the “timesCalled” variable.

The final step is to assert whether the “timesCalled” variable equals 3.

See example:

When should you use the TIMES_CALLED macro?
– When you need to count the number of times a specific method was called.

2) ISOLATOR_INVOKE_CONSTRUCTOR Macro:
In the next example, we invoke class Person’s constructor.

First, we fake an object of type Person(“fakePerson”).
Then, we instantiate a variable of type char* (“lastName”) and we assign “Smith” into it.

Next, we use the ISOLATOR_INVOKE_CONSTRUCTOR macro from our API, which receives the faked object(“fakePerson”) and the “lastName” variable.
This action activates the constructor of ‘class Person’ which assigns the char* variable(“lastName”)   into the faked object(“fakePerson”) last_name field.

The final step is to assert whether the “lastName” variable equals to the last_name field of “fakePerson”.

See example:

When should you use the ISOLATOR_INVOKE_CONSTRUCTOR macro?
– When you need to check if the constructor initializes the lastname field as it should or if you want to access the constructor of a fake object.

Note: ISOLATOR_INVOKE_CONSTRUCTOR can be called only once per object’s lifetime.

3) FAKE_GLOBAL Macro:
In the next example, we fake the global “fopen” and “fclose” methods.

First, we fake the methods using the FAKE_GLOBAL macro from our API.

Then, we instantiate a variable of type FILE* (“fp”) and we assign ‘NULL’ into it.

Next, we use the WHEN_CALLED macro from our API, which receives the faked global method(“fopen”) with no arguments, and then we change the behavior of the method so it will return ‘NULL’ in any case.

The next step is to call the global method.

In our case, we need to instantiate a variable of type Person(person) and use it to call a method that calls the global method (fopen). As you can see in the example we call the method “SaveData” that does that.

Inside the “SaveData” method we call the global method “fopen”(we expect it will return ‘NULL’), and indeed we can see that “fp” equals ‘NULL’ so the if condition is false and the method “fclose” is not called.

The final step is to assert whether the global method “fclose” was called(we use the ASSERT_NOT_CALLED macro from our API).

See example:

When should you use the FAKE_GLOBAL macro?
– When you need to fake a global function.

4) DoStaticOrGlobalInstead Macro:
In the next example, we change the behavior of the global function “GetTickCount”.

First, we fake the method(“GetTickCount”) using the FAKE_GLOBAL(see example 3) macro (from our API).
Then, we use the WHEN_CALLED macro(from our API) and the DoStaticOrGlobalInstead macro that receives the method we want to execute when “GetTickCount” is called. In our case, we want to execute the “GetOtherTickCount” method.

The next step is calling the “GetTickCount” method. What really needs to happen is that “GetOtherTickCount” will be called and return 10,000 into “result” variable.

The final step is to assert whether the “result” variable equals to the value that “GetOtherTickCount” returns(10,000).

See example:

When should you use the DoStaticOrGlobalInsted macro?
– When you need to change the behavior of a specific global function.

5) ISOLATOR_SET/GET _VARIABLE Macros:
In the next example, we set into a private member/ get from a private member.

First, we instantiate a variable of type Person* (“person”).

Then, we use the ISOLATOR_SET_VARIABLE macro(from our API) which gets the instantiated variable(in our case is “person”), the private member we want to set(in out case is “m_id”) and for last the value we want to set.

The next step is to instantiate a variable(in our case of type int-”memberValue”) and then use the ISOLATOR_GET_VARIABLE macro (from our API) which also gets the instantiated variable(“person”), the private member we want to set(“m_id”) and for last the variable we want to set into.

The final step is to assert whether the “memberValue” variable equals to the value we set into the private member(“m_id”), meaning equals to 10.
Of course, we don’t forget to delete the variable we instantiate(person).

See example:

When should you use the ISOLATOR_SET/GET_VARIABLE macro?
– When you need to extract value from a private member or you want to insert into a variable(from a private member), or both as you can see in the example.

6) Faking a public method:
In the next example, we are faking the method “GetName”.
First, we instantiate a variable of type Person (“person”).

Then, we use the WHEN_CALLED macro(from our API) which receives the public method we want to fake (“GetName”), and then we use the Return macro that receives the value we want to get every time we call the method(“GetName”). In this specific example, we return the string “Tommy”.

The final step is to assert whether the returned value from the call to the method “GetDogName” which you can see in the example calls the method we faked(“GetName”) is equal to the string “Lassie”.

See example:

When should you use the WHEN_CALLED+Return macros?
– One of the cases you should use them is when you want to control the returned value of a specific public method.

7) Faking an exception throwing:
In the next example, we fake an exception throw.

First, we instantiate a variable of type Person (“person”), we fake a variable of type Address* (“fakeAddress”) and we instantiate a variable of type exception(“problem”).

Then, we use the WHEN_CALLED macro(from our API) which receives the calling of the method(“GetCountry”) with our faked variable(“fakeAddress”) and we change the behavior of the method with our Throw macro so when it is called we throw an exception.

The next step we instantiate a variable of type string(“error”).
Then, we instantiate a variable of type string(“result”) and we insert the value that returns from the calling of the method(“GetAddressCountry”) which as you can see throws the exception and returns the string “Error”.

The final step is to assert whether the “result” variable equals the value of the string that was instantiated earlier (“error”).

See example:

When should you use the Throw macro?
– When you want to throw an exception when a method is called.

We hope you found these tips and tricks helpful. The next blog post will have six more, stay tuned 🙂

*Update: We posted the second part. Find more C++ unit testing tips and tricks HERE.