Conditional Behavior Faking

Top  Previous  Next

Isolator++ Professional allows you to return different values of a faked method, based on parameter values.

To do this use the Conditional Checkers in the WHEN_CALLED statement.

 

API

Meaning

Example

_

All arguments are ok

WHEN_CALLED(fake->Foo(_)).Return(1);

ANY_VAL

All arguments are ok (value types)

WHEN_CALLED(fake->Foo(ANY_VAL(Type))).Return(1);

ANY_REF

All arguments are ok (byref)

WHEN_CALLED(fake->Foo(ANY_REF(Type))).Return(1);

EQ

Arg must equal (using == operator)

WHEN_CALLED(fake->Foo(EQ(100))).Return(1);

NE

Arg must not equal

WHEN_CALLED(fake->Foo(NE(3))).Return(1);

LT

Arg is smaller than

WHEN_CALLED(fake->Foo(LT(5))).Return(1);

LE

Arg is smaller or equals

WHEN_CALLED(fake->Foo(LE(4))).Return(1);

GT

Arg is greater than

WHEN_CALLED(fake->Foo(GT(10.2))).Return(1);

GE

Arg is greater or equals

WHEN_CALLED(fake->Foo(GE(1))).Return(1);

IS

Arg must pass lamda function

WHEN_CALLED(fake->Foo(IS(<char*>([](char* s) {return  !strcmp(s, "typemock");}))).Return(1);

IS_REF

By Ref Arg must pass lamba function

WHEN_CALLED(fake->Foo(IS_REF(<cosnt char*>([](const char* s) {return  !strcmp(s, "typemock");}))).Return(1);

RET_IF

Assign out value, if condition is true

WHEN_CALLED(fake->Foo(RET_IF(EQ(&value), &out)).Return(1);

BY_REF

Use in condition macros to assign value directly

WHEN_CALLED(fake->Foo(RET_IF(EQ(BY_REF("typemock")), &out)).Return(1);

 

Note: You can use BY_REF only on reference-type parameters. All object comparisons (std::string for example) must be done using IS.
EQ/NE can be used on natives and pointers.

 

linuxsymbol Note: If multiple conditional faking and unconditional faking are set up. Isolator++ Professional will try to find a match with the conditional behaviors first, and will sequence them, only if no conditional behavior is found will the unconditional behaviors be used.

 

Example

 

Assuming the following class is in the production code:

 

class Person

{

public:

   bool IsPartOfGroup(int newGroupID) ; 

};

 

Let's create a test that will return true only for group 2

 

TEST_F(Examples, ConditionalForInstanceMethod)

{

   Person* livePerson = new Person();        

 

   WHEN_CALLED(livePerson->IsPartOfGroup(EQ(2))).Return(true);

 

   ASSERT_EQ(true, livePerson->IsPartOfGroup(2));

 

   ISOLATOR_CLEANUP();

}

 

Example with Private Methods

 

Using the same example as above, assuming IsPartOfGroup is private:

 

 

PRIVATE_WHEN_CALLED(livePerson,IsPartOfGroup,EQ(2)).Return(true);

 

 

Creating Custom Conditions

 

To create custom conditions, use the IS<> macro and implement the condition within the lambda method.

Using the previous code, Let's create a test that will return true only for groups 2 and 5.

 

TEST_F(Examples, ConditionalForInstanceMethod)

{

   Person* livePerson = new Person();        

 

   WHEN_CALLED(livePerson->IsPartOfGroup(IS(<int>([](int& i) {return  i==2 || i==5 ;}))).Return(true);

 

   ASSERT_EQ(true, livePerson->IsPartOfGroup(2));

 

   ISOLATOR_CLEANUP();

}

 

 

Note: The IS<> macro is also used for specifying an overload of the method with the matching arguments.

 

Note: When there is no lambda expressions support, you can use a predicate class with overloaded ().

You'll need to define NO_CPP_LAMBDA_SUPPORT:

 

#define NO_CPP_LAMBDA_SUPPORT

 

struct Predicate{

   bool operator()(int x){return  i==2 || i==5 ;}

}

 

// And the relevant change in the code will be:

WHEN_CALLED(livePerson->IsPartOfGroup(IS(<int>(Predicate()))).Return(true);

 

 

Example with out/by-ref value-type parameter

 

Assuming the following class is in the production code, that has a method with an out argument that we want to conditionally fake

 

class Person

{

public:

 

   char* name;

 

   bool GetNameWithRef(char** refName)

   {

 *refName = name;

      return false; 

   }

};

 

Let's create a test that will return false only for referenced name "typemock" using RET_IF macro.

 

TEST_F(Examples, RefBehaviorChanging)

{

   Person* livePerson = new Person();

   livePerson->name = "foo";        

 

   char* name = "bar";

   chartypemock = "typemock";

 

   WHEN_CALLED(livePerson->GetNameWithRef(RET_IF(EQ(&typemock), &name)).Return(true)// will set argument to name if it was "typemock"

 

   char* result = "typemock";

   ASSERT_TRUE(livePerson->GetNameWithRef(&result));

   ASSERT_EQ(result,name);

 

   ISOLATOR_CLEANUP();

}

 

Note: Use a pointer to the value to RET or use BY_REF

 

 

   WHEN_CALLED(livePerson->GetNameWithRef(RET_IF(EQ(BY_REF("typemock")), &name)).Return(true)// will set argument to name if it was "typemock"

 

 

Creating Custom Conditions between many arguments

 

To create a condition that requires testing multiple arguments between each other, use the DoInstead api, and put the logic within the alternative implementation.
Note: Isolator++ Professional manages DoInstead as an unconditional statement and thus will be used after all conditions.

 

Note: the following example uses DoStaticOrGlobalInstead but you can use DoMemberFunctionInstead too.

 

Example

 

Assuming the following class is in the production code:

 

class Person

{

public:

   bool IsPartOfGroup(int newGroupID, char *name)const {

   return false} 

};

 

Let's create a test that will return true only for group 2 with name "typemock"

 

static bool TrueIf2AndTypemock(int newGroupID, const char *name

{

   return newGroupID == 2 && !strcmp(name"typemock");

}

 

TEST_F(Examples, DoInsteadForInstanceMethod)

{

   Person* livePerson = new Person();        

 

   WHEN_CALLED(livePerson->IsPartOfGroup(_,_)).DoStaticOrGlobalInstead(TrueIf2AndTypemock, nullptr);

 

   ASSERT_EQ(true, livePerson->IsPartOfGroup(2"typemock"));

 

   ISOLATOR_CLEANUP();

}

 

 

 


Copyright  Typemock Ltd. 2009-2025.  All Rights Reserved.