How-To: Asserting A Method Was Called With Isolator++

Many times, when we come to determine a test pass/fail criterion, we use some sort of ASSERT statement. ASSERT usually tests for state – checking on field values, to determine if that value is the expected one.

However, sometimes we don’t have this luxury. The state may not be exposed, or the class members are private. Either way, we can’t use them.

But there are ways to make sure things have happened. When we test a variable for test, we’re actually making sure that the logic we’re testing is resulting in a state change. How about testing that what we expected actually happened?

In other words, if we’re testing Person, which calls an Address method, we can actually test, with Isolator++, that the method was called.

Here is our Person method we want to test:

void Person::UpdateAddress(Address* newAddress)

{

    address->SetCountry(newAddress->GetCountry());

}

Let’s assume that address inaccessible. It’s initially set in the constructor, never to be seen again:

Person::Person(Address* initialAddress)

{

    address = initialAddress;

}

Address is also problematic in terms of incompleteness. Here’s its GetCountry method:

char* GetCountry()

{

    throw ("Not implemented yet!");

}

How can we make sure that UpdateAddress really does what it’s supposed to? Let’s look at the test:

    1 TEST_F(PersonTests, UpdateAddress_ValidAddress_AddressIsSet)

    2 {

    3     // Setting up a fake initial address

    4     Address* oldAddress = FAKE<Address>();

    5     Person person(oldAddress);

    6 

    7     // Setting up a fake updated address

    8     Address* newAddress = FAKE<Address>();

    9     WHEN_CALLED(newAddress->GetCountry()).ReturnPtr("US");

   10 

   11     person.UpdateAddress(newAddress);

   12 

   13     ASSERT_WAS_CALLED(oldAddress->SetCountry(_));

   14     ISOLATOR_CLEANUP();

   15 }

As you can see, we’re setting up two fake Address objects:

  • Line 4: The initial Address object, on which we’re going to test SetCountry was called. Note we’re not setting any behavior on the SetCountry method – it’s ignored by default because the object is faked.
  • Line 8: The new Address.
  • Line 9: We also set a behavior using WHEN_CALLED on the new one, so it won’t crash when GetCountry is called
  • Line 13: Using ASSERT_WAS_CALLED we test that method was called. If it wasn’t called before this line, the test would fail. By the way, by using the (_) macro as an argument, I’m telling Isolator to disregard any argument calls at runtime – what matters to me is that the method was called.
  • Line 14: Cleaning up the faking statements

Using ASSERT_WAS_CALLED and it’s brother macro ASSERT_NOT_CALLED (which, as you can guess passes the test if the method was not called) you can actually set a pass/fail criteria on method calls.

Do you want to know more about Isolator++? Check out the online guide.