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.
Note: You can use BY_REF only on reference-type parameters. All object comparisons (std::string for example) must be done using IS.
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(); }
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"; char* typemock = "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: 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.