Conditional Behavior Faking |
Top Previous Next |
Isolator++ Professional allows you to return different values of a faked method, based on parameter values. To achieve this use the Conditional Checkers in the CallTo statement.
Note: Use the Ref APIS for by reference-type parameters.
Note: Isolator++ Professional prioritizes conditional fakes and sequences them. If no match is found, unconditional behaviors are used.
Examples
Example 1: Conditional for Instance Method
Assuming the following class is in the production code:
class Person { public: bool IsPartOfGroup(int newGroupID) ; };
To create a test that returns true only for group 2:
TEST_F(Examples, ConditionalForInstanceMethod) { // Arrange auto a = Isolator(); Person* livePerson = new Person();
a.CallTo(livePerson->IsPartOfGroup(A::Eq(2))).WillReturn(true);
// Act auto result = livePerson->IsPartOfGroup(2);
// Assert ASSERT_TRUE(result); }
Note: Isolator++ native operators (A::Eq etc.) also accept objects if the underlying operators exist for the objects. Assume we have a class Logger, with an instance method WriteStringLine(const std::string&) that prints an std::string. You can verify that the method was called with a specific string like this:
TEST_F(Examples, ConditionalForInstanceMethod) { // Arrange auto a = Isolator(); auto logger = a.Fake.Instance<Logger>();
logger->WriteStringLine("hello"); logger->WriteStringLine("goodbye");
// Act auto result1 = a.CallTo(logger->WriteStringLine(A::Eq("hello")).GetTimesCalled(); auto result2 = a.CallTo(logger->WriteStringLine(A::Ne("hello")).GetTimesCalled();
//It is possible as well with A::Matches API) auto result3 = a.CallTo(logger->WriteStringLine(A::Matches([](const std::string& str) { return str == "hello"; })).GetTimesCalled();
// Assert ASSERT_EQ(result1, 1); ASSERT_EQ(result2, 1); ASSERT_EQ(result3, 1); }
Here is an example for the other native operators (the comparison is alphabetical for std::string):
TEST_F(Examples, ConditionalForInstanceMethod) { auto a = Isolator(); auto logger = a.Fake.Instance<Logger>();
logger->WriteStringLine("apple"); logger->WriteStringLine("banana"); logger->WriteStringLine("cat"); logger->WriteStringLine("dog");
auto res = a.CallTo(logger->WriteStringLine(A::Lt("dog"))).GetTimesCalled(); ASSERT_EQ(res, 3);
res = a.CallTo(logger->WriteStringLine(A::Le("dog"))).GetTimesCalled(); ASSERT_EQ(res, 4);
res = a.CallTo(logger->WriteStringLine(A::Gt("apple"))).GetTimesCalled(); ASSERT_EQ(res, 3);
res = a.CallTo(logger->WriteStringLine(A::Ge("apple"))).GetTimesCalled(); ASSERT_EQ(res, 4); }
Example 2: Conditional for Reference-Type Argument
Assume the following class:
class Person { public: bool IsPartOfGroupRef(int& newGroupID) ; };
To create a test that returns true only for group 2:
TEST_F(Examples, ConditionalForInstanceMethod) { // Arrange auto a = Isolator(); Person* livePerson = new Person();
a.CallTo(livePerson->IsPartOfGroupRef(A::EqRef(2))).WillReturn(true);
// Act int id = 2; auto result = livePerson->IsPartOfGroup(id);
// Assert ASSERT_TRUE(result); }
Example 3: Conditional for Private Method
If the method IsPartOfGroup is private, use CallToPrivate:
a.CallToPrivate(A::Member(livePerson, IsPartOfGroup),A::Eq(2))).WillReturn(true);
Example 4: Conditional for Private Method
To create a custom condition, use A::Matches with a lambda. For example, return true for groups 2 and 5:
TEST_F(Examples, ConditionalForInstanceMethod) { // Arrange auto a = Isolator(); Person* livePerson = new Person();
a.CallTo(livePerson->IsPartOfGroup(A::Matches([](int i) {return i==2 || i==5 ;})) .WillReturn(true);
// Act auto result = livePerson->IsPartOfGroup(2);
// Assert ASSERT_TRUE(result); }
Note: The A::Matches API can be used for specifying an overload of the method with the matching arguments.
Example 5: Out/By-Ref Parameter
If you need to conditionally fake a method with an out parameter:
class Person { public:
char* name;
bool GetNameWithRef(char** refName) { *refName = name; return false; } };
Test to return true and set the out parameter to "bar" when the referenced name is "typemock":
TEST_F(Examples, RefBehaviorChanging) { // Arrange auto a = Isolator(); Person* livePerson = new Person(); livePerson->name = "foo";
// will set argument to bar if it was "typemock" a.CallTo(livePerson->GetNameWithRef(A::SetOut("bar").WhenIn(A::EqRef("typemock")).WillReturn(true);
char* arg = "typemock"; // Act auto result = livePerson->IsPartOfGroup(arg);
// Assert ASSERT_TRUE(result); ASSERT_STREQ(arg,"bar"); }
Note: We use A::EqRef as the argument is a pointer
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 lambda.
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 returns true only for group 2 with name "typemock"
TEST_F(Examples, DoInsteadForInstanceMethod) { // Arrange auto a = Isolator(); Person* livePerson = new Person();
a.CallTo(livePerson->IsPartOfGroup(A::Any(),A::Any())).WillDoInstead([](int newGroupID, const char *name) { return newGroupID == 2 && !strcmp(name, "typemock"); });
// Act auto result = livePerson->IsPartOfGroup(2, "typemock");
// Assert ASSERT_TRUE(result); }
|
Copyright Typemock Ltd. 2009-2025. All Rights Reserved.