-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IgnoreParameter not working? #12
Comments
Hmmm. The code did not show up formatted nicely in my original post above. So let me attach the sample source code that shows the error. |
Jesús González, void namespace1::class6::method1(const char* p1, int p2) And the expect: namespace expect { |
Now that I figured out the code blocks. Let's try this modification code again. // new mock modification: skip object check by passing in "nullptr"
void namespace1::class6::method1(const char* p1, int p2)
{
const bool __object__isIgnored = mock().getData("namespace1::class6::method1__object___isIgnored").getBoolValue();
namespace1::class6* thisPtr = (__object__isIgnored) ? nullptr : this;
mock().actualCall("namespace1::class6::method1").onObject(thisPtr).withStringParameter("p1", p1).withIntParameter("p2", p2);
} And the expect changes: // new expect modification: pass the object.isIgnored() flag
namespace expect {
namespace namespace1$ {
namespace class6$ {
MockExpectedCall& method1(CppUMockGen::Parameter<const namespace1::class6*> __object__, CppUMockGen::Parameter<const char*> p1, CppUMockGen::Parameter<int> p2)
{
bool __ignoreOtherParams__ = false;
MockExpectedCall& __expectedCall__ = mock().expectOneCall("namespace1::class6::method1");
mock().setData("namespace1::class6::method1__object___isIgnored", __object__.isIgnored());
if (!__object__.isIgnored()) { __expectedCall__.onObject(const_cast<namespace1::class6*>(__object__.getValue())); }
if (p1.isIgnored()) { __ignoreOtherParams__ = true; }
else { __expectedCall__.withStringParameter("p1", p1.getValue()); }
if (p2.isIgnored()) { __ignoreOtherParams__ = true; }
else { __expectedCall__.withIntParameter("p2", p2.getValue()); }
if (__ignoreOtherParams__) { __expectedCall__.ignoreOtherParameters(); }
return __expectedCall__;
}
}
}
} |
I am not sure the previous modification will work? So let's try another example. #ifndef CLASS2MOCK_H
#define CLASS2MOCK_H
class Class2Mock
{
public:
void method();
};
#endif//CLASS2MOCK_H Run it through this AWESOME CppUMockGen tool and get the mock: // Slight modification to handle ignoring the object by using mock().setData()
void Class2Mock::method()
{
#if 1 // enhancement
static std::size_t actualCallCount = 0;
const std::string callString = "Class2Mock::method::call(" + std::to_string(++actualCallCount) + ").isIgnored";
const bool __object__isIgnored = mock().getData(callString.c_str()).getBoolValue();
Class2Mock* thisPtr = (__object__isIgnored) ? nullptr : this;
mock().actualCall("Class2Mock::method").onObject(thisPtr);
#else // original mock code
mock().actualCall("Class2Mock::method").onObject(this);
#endif
} Now the expect generated code: namespace expect { namespace Class2Mock$ {
MockExpectedCall& method(CppUMockGen::Parameter<const Class2Mock*> __object__)
{
#if 1 // enhancement
return method(1, __object__);
#endif
}
MockExpectedCall& method(unsigned int __numCalls__, CppUMockGen::Parameter<const Class2Mock*> __object__)
{
#if 1 // enhancement
static std::size_t expectedCallCount = 0;
for (unsigned int i = 0; i < __numCalls__; ++i)
{
const std::string callString = "Class2Mock::method::call(" + std::to_string(++expectedCallCount) + ").isIgnored";
mock().setData(callString.c_str(), __object__.isIgnored());
}
MockExpectedCall& __expectedCall__ = mock().expectNCalls(__numCalls__, "Class2Mock::method");
Class2Mock* thisPtr = (__object__.isIgnored()) ? nullptr : const_cast<Class2Mock*>(__object__.getValue());
__expectedCall__.onObject(thisPtr);
return __expectedCall__;
#else // original expect code
MockExpectedCall& __expectedCall__ = mock().expectNCalls(__numCalls__, "Class2Mock::method");
if(!__object__.isIgnored()) { __expectedCall__.onObject(const_cast<Class2Mock*>(__object__.getValue())); }
return __expectedCall__;
#endif
} Again, I am not sure this is the best way to fix the original issue? But this does work for now. |
First off, thank you for this wonderful tool. It is excellent and will save us a lot of time creating and maintaining mocks!
Sometimes the TESTs we write have no control over the mock's object instance. Only the unit under test does. So there is a need to ignore the class's object instance check. However, I am seeing a problem attempting to skip the object check. For example:
`
// class6.h
namespace namespace1
{
class class6
{
public:
void method1(const char* p1, int p2);
};
}
// class6.cpp
/*
#include
#include "class6.h"
namespace namespace1
{
void class6::method1(const char* p1, int p2)
{
if ((strcmp(p1, "hello") == 0) && (p2 == 42))
{
// do something
}
}
}*/
// class6_mock.cpp
/*
/
//#include "class6.h"
#include <CppUTestExt/MockSupport.h>
void namespace1::class6::method1(const char p1, int p2)
{
mock().actualCall("namespace1::class6::method1").onObject(this).withStringParameter("p1", p1).withIntParameter("p2", p2);
}
// class6_expect.hpp
/*
/
#include <CppUMockGen.hpp>
//#include "class6.h"
#include <CppUTestExt/MockSupport.h>
namespace expect {
namespace namespace1$ {
namespace class6$ {
MockExpectedCall& method1(CppUMockGen::Parameter<const namespace1::class6> object, CppUMockGen::Parameter<const char*> p1, CppUMockGen::Parameter p2, bool return);
MockExpectedCall& method1(unsigned int numCalls, CppUMockGen::Parameter<const namespace1::class6*> object, CppUMockGen::Parameter<const char*> p1, CppUMockGen::Parameter p2, bool return);
}
}
}
// class6_expect.cpp
/*
/
//#include "class6_expect.hpp"
namespace expect {
namespace namespace1$ {
namespace class6$ {
MockExpectedCall& method1(CppUMockGen::Parameter<const namespace1::class6> object, CppUMockGen::Parameter<const char*> p1, CppUMockGen::Parameter p2)
{
bool ignoreOtherParams = false;
MockExpectedCall& expectedCall = mock().expectOneCall("namespace1::class6::method1");
if (!object.isIgnored()) { expectedCall.onObject(const_castnamespace1::class6*(object.getValue())); }
if (p1.isIgnored()) { ignoreOtherParams = true; }
else { expectedCall.withStringParameter("p1", p1.getValue()); }
if (p2.isIgnored()) { ignoreOtherParams = true; }
else { expectedCall.withIntParameter("p2", p2.getValue()); }
if (ignoreOtherParams) { expectedCall.ignoreOtherParameters(); }
return expectedCall;
}
MockExpectedCall& method1(unsigned int numCalls, CppUMockGen::Parameter<const namespace1::class6*> object, CppUMockGen::Parameter<const char*> p1, CppUMockGen::Parameter p2)
{
bool ignoreOtherParams = false;
MockExpectedCall& expectedCall = mock().expectNCalls(numCalls, "namespace1::class6::method1");
if (!object.isIgnored()) { expectedCall.onObject(const_castnamespace1::class6*(object.getValue())); }
if (p1.isIgnored()) { ignoreOtherParams = true; }
else { expectedCall.withStringParameter("p1", p1.getValue()); }
if (p2.isIgnored()) { ignoreOtherParams = true; }
else { expectedCall.withIntParameter("p2", p2.getValue()); }
if (ignoreOtherParams) { expectedCall.ignoreOtherParameters(); }
return expectedCall;
}
}
}
}
void unit_under_test(const char* p1, int p2)
{
namespace1::class6 class6_object_instance;
class6_object_instance.method1(p1, p2);
}
TEST_GROUP(class6)
{
void setup() {}
void teardown() { mock().clear(); }
};
TEST(class6, method1_check_object)
{
namespace1::class6 class6_mock;
}
TEST(class6, method1_ignore_object)
{
// The unit under test controls the lifecycle of the mock object so ignore the object parameter!
expect::namespace1$::class6$::method1(CppUMockGen::IgnoreParameter::YES, "hello", 42);
unit_under_test("hello", 42); // <-- EXCEPTION here!
mock().checkExpectations();
}
/*
Failure in TEST(class6, method1_ignore_object)
MockFailure: Function called on an unexpected object: namespace1::class6::method1
Actual object for call has address: <007FE96B>
EXPECTED calls that DID NOT happen related to function: namespace1::class6::method1
namespace1::class6::method1 -> const char* p1: , int p2: <42>
ACTUAL calls that DID happen related to function: namespace1::class6::method1
..
Errors (1 failures, 2 tests, 2 ran, 2 checks, 0 ignored, 0 filtered out, 24 ms)
*/
`
I used your example in the documentation page, "namespace1::class6::method", to generate the class6 mock.
The text was updated successfully, but these errors were encountered: