Gmock doesn't work as exected.
EXPECT_CALL doesn't call mock functions.
Here is the code snippet:
In Header.hpp:
typedef MockITest ITest;
Class mainclass
{
public:
std::shared_ptr<ITest> mTestCtrl;
funcToTest();
};
source.cpp
{
std::shared_ptr<mainclass> mainclassPtr;
funcToTest()
{
mTestCtrl = getCtrl();
if( nullptr != mTestCtrl){
cout<< "I can see print here";
mTestCtrl->start();
}
}
}
samplemock.h
class MockITest
{
public:
/// #brief function mock
MOCK_METHOD0(start, void());
};
std::shared_ptr<MockITest> getCtrl()
{
return std::make_shared<MockITest>();
}
test.cpp
TEST_F(TestMqttgwProcessKeepAlive, Test_funcToTest)
{
mainclassPtr = std::make_shared<mainclass>();
mainclassPtr->funcToTest();
EXPECT_CALL(*mainclassPtr->mTestCtrl.get(), start()).Times(1);
}
I get this error.
Uninteresting mock function call - returning directly.
Function call: start()
Actual function call count doesn't match EXPECT_CALL(*mainclassPtr->mTestCtrl.get(), start())...
Expected: to be called once
Actual: never called - unsatisfied and active
I think you should put EXPECT_CALL before the call to funcToTest:
TEST_F(TestMqttgwProcessKeepAlive, Test_funcToTest)
{
mainclassPtr = std::make_shared<mainclass>();
EXPECT_CALL(*mainclassPtr->mTestCtrl.get(), start()).Times(1);
mainclassPtr->funcToTest();
}
In general, expectations should come first, then calls to the functions that are expected to be called.
Related
I am about to write a custom ESPHome component. I don't have much experience with C language and I am facing some troubles using external library.
For demonstration, I prepared a simple component class..
class Test: public Component {
public:
auto t = timer_create_default();
void setup() override {
ESP_LOGD("TEST", "Test setup called!");
t.every(1000, TestLog);
}
void loop() override {
ESP_LOGD("TEST", "Test loop called!");
t.tick();
}
bool TestLog(void *) {
ESP_LOGD("TEST", "TestLOG!");
return true;
}
}
With this, I receive:
In file included from src\main.cpp:32:0: src\Test.h:7:35: error:
non-static data member declared 'auto'
auto t = timer_create_default();
I took it from some example where they did not have the class, but I can't find out, how to use it.
The library is:
https://github.com/contrem/arduino-timer/
I can still rewrite it without this timer completely and handle it only in the loop function, but I would like to understand what I am doing wrong.
If I change the return type to Timer<> I got another error:
src\Test.h: In member function 'virtual void Test::setup()':
src\Test.h:11:24: error: no matching function for call to
'Timer<>::every(int, )'
t.every(1000, TestLog);
You can not use auto to declare non-static member variables so you need to replace auto with the type returned by timer_create_default().
If you are not sure what type it returns, you can simply use decltype in the declaration:
decltype(timer_create_default()) t = timer_create_default();
If I read the code in the repo correctly, the returned type is Timer<>, so this should also work:
Timer<> t = timer_create_default();
or simply:
Timer<> t;
Also: The function pointer passed to t.every() should be a bool (*)(void*) but TestLog is a non-static member function and the pointer type is bool (Test::*)(void*) - You can fix that by making TestLog static:
class Test: public Component {
public:
// ...
static bool TestLog(void *) {
ESP_LOGD("TEST", "TestLOG!");
return true;
}
};
If you want to get the Test instance in the TestLog callback, make the Timer
Timer<TIMER_MAX_TASKS, millis, Test*> t;
and change TestLog:
class Test: public Component {
public:
// ...
static bool TestLog(Test* t) {
ESP_LOGD("TEST", "TestLOG!");
return true;
}
};
and in setup():
t.every(1000, TestLog, this);
You'll now get a pointer to the Test instance in the TestLog callback and you can use this to call a non-static member function in Test.
Full example:
class Test : public Component {
public:
Timer<TIMER_MAX_TASKS, millis, Test*> t;
void setup() override {
ESP_LOGD("TEST", "Test setup called!");
// call the static member function every second:
t.every(1000, TestLogProxy, this);
}
void loop() override {
ESP_LOGD("TEST", "Test loop called!");
t.tick();
}
bool TestLog() {
ESP_LOGD("TEST", "TestLOG!");
return true;
}
static bool TestLogProxy(Test* t) {
// forward the callback call to the non-static member function:
return t->TestLog();
}
};
In the code Google Mock test snippet there is an EXPECT_CALL that returns True and an argument reference for 200 times.
How can I let the test only return True every nth time. For example return True each 10th call and otherwise return False.
class MockHandler : public Handler
{
public:
MOCK_METHOD1(RxMsg, bool(Msg &msg));
}
TEST(TestDispatcher, HandlePing)
{
auto mockedHandler = make_unique<MockHandler>();
Msg rxMsg = { REQUEST::REQ_PING, sizeof(DefaultMsg_t), rxMsg.rx,(uint8_t*)"0"};
EXPECT_CALL(*mockedHandler,
RxMsg(_)).Times(checkValue).WillRepeatedly(
DoAll(SetArgReferee<0>(rxMsg), Return(TRUE)));
Dispatcher dispatcher(10, mockedHandler);
for (int i = 0; i < 199; i++)
{
dispatcher.RunToCompletion();
}
}
There are few approaches that might work for you. I like the solution with Invoke as a default action, because it is the most flexible. You didn't provide mcve in your question, so I wrote very simple implementations for the classes you use. Also you made a mistake using unique_ptr for the mock. In 99% of cases is must be shared_ptr, because you are sharing it between testing environment and your System Under Test.
class Msg {};
class Handler {
public:
virtual bool RxMsg(Msg &msg) = 0;
};
class MockHandler: public Handler
{
public:
MOCK_METHOD1(RxMsg, bool(Msg &msg));
};
class Dispatcher {
public:
Dispatcher(std::shared_ptr<Handler> handler): h_(handler) {}
void run() {
Msg m;
std::cout << h_->RxMsg(m) << std::endl;
}
private:
std::shared_ptr<Handler> h_;
};
class MyFixture: public ::testing::Test {
protected:
MyFixture(): mockCallCounter_(0) {
mockHandler_.reset(new MockHandler);
sut_.reset(new Dispatcher(mockHandler_));
}
void configureMock(int period) {
ON_CALL(*mockHandler_, RxMsg(_)).WillByDefault(Invoke(
[this, period](Msg &msg) {
// you can also set the output arg here
// msg = something;
if ((mockCallCounter_++ % period) == 0) {
return true;
}
return false;
}));
}
int mockCallCounter_;
std::shared_ptr<MockHandler> mockHandler_;
std::unique_ptr<Dispatcher> sut_;
};
TEST_F(MyFixture, HandlePing) {
configureMock(10);
for (int i = 0; i < 199; i++) {
sut_->run();
}
}
At the beginning of each test you should call configureMock method that will Invoke ON_CALL macro setting the default action for your mock. Function passed to Invoke can be any function matching the signature of the method you are overwriting. In this case it;s a function that counts how many times mock has already been called and returns appropriate value. You can also assign some particular object to the msg output argument.
I have a mocked function that when I run in a unit test with the anything matcher ('_') the unit test fails because GMock can't find a matched function.
Here is my mocked class and function:
class MockedClass {
public:
MockedClass() {};
~MockedClass() {};
MOCK_METHOD1(unregisterClient, bool(const ThriftClient& tClient));
};
class ConnectionClass {
public:
ConnectionClass() {};
~ConnectionClass() {};
bool unregisterClient(ThriftClient& tClient)
{
bool ret = false;
if (mock_ != NULL)
ret = mock_->unregisterClient(tClient);
return ret;
}
static MockedClass *mock_;
};
MockedClass *ConnectionClass::mock_ = NULL;
Here is the function under test:
class RealObject {
public:
RealObject(ConnectionClass &cc);
void unregister();
private:
ConnectionClass &cc_;
ThriftClient tClient_;
}
RealObject::RealObject(ConnectionClass &cc) {
cc_ = &cc;
}
void RealObject::unregister() {
cc_->unregisterClient(tClient_);
}
Here is the test function:
TEST_F(Test, UnregisterTest) {
MockedClass mclass;
ConnectionClass cc;
cc.mock_ = &mclass;
RealObject obj(cc);
EXPECT_CALL(mclass, unregisterClient(_)).WillOnce(Return(true));
obj.unregister(); // Calls mocked function
}
Here is the failure message:
Test.cpp:142: Failure Actual function call count doesn't match
EXPECT_CALL(mclass, unregisterClient(_))...
Expected: to be called once
Actual: never called - unsatisfied and active
I have also tried:
EXPECT_CALL(mclass, unregisterClient(Matcher<const ThriftClient&>(_))).WillOnce(Return(true));
EXPECT_CALL(mclass, unregisterClient(An<const ThriftClient&>())).WillOnce(Return(true));
All with the same failure message.
Why am I getting this failure message? I don't understand why GMock can't match the function call.
The problem i have that i have several functions that needs to be invoked in defined order the order can't be breakable.
now the code need to be continued and develop after i finish to code.
im looking for some method to set the functions in some kind of unbreakable structure.
for example i have:
function_1() { //do some stuff ..} ; // must be first
function_2() { //do some stuff based on function_1()..}; // must be second
function_3() { //do some stuff based on function_1() and function_2()..};; // must be third
they all under the main() app function .
Create another function for public access, that guarantees the other three functions are called in the correct order. To prevent those functions are visible with the public API, you can hide them in an unnamed namespace.
In your header put
bool function_4();
In your corresponding translation unit you create an unnamed namespace to prevent others from seeing those functions
namespace {
bool function_1() {
}
bool function_2() {
}
bool function_3() {
}
}
And define function_4
bool function_4() {
return function_1() &&
function_2() &&
function_3();
}
I suppose that you have some solid reasons not to wrap all these three functions into one single function.
In this case the simplest approach, would be to manage a status that is shared between all the three functions:
static int function_status=0; // shared status: nothing was called
function_1() {
if (status>0)
throw exception ("function_1 MUST be called first and only once");
status=1; // function_1 was called
...
}
function_2() {
if (status<1)
throw exception ("function_1 MUST be called before 2");
else if (status>2) // I suppose function 2 could be called several times
throw exception ("function_2 CANNOT be called after 3");
status = 2;
...
}
function_3() {
if (status<2)
throw exception ("function_2 MUST be called before 3");
else if (status==3)
throw exception ("function_3 CAN ONLY BE CALLED ONCE");
status = 3;
...
}
As you see, this status gives you the opportunity to check very precisely if the flow of execution respects the logic that you want.
You can create a wrapping function
bool execute()
{
return function_1() && function_2() && function_3();
}
The functions will be called in order, and it will short circuit if any of the functions fail. Assuming the functions return a bool indicating success/failure, if the function returns true all functions successfully completed, otherwise at least one of them failed.
The simple case of ordering functions is to make a single function that is called by the user, that does all three of the subfunctions. However, this doesn't always work. The user may need to do some processing after function1 before calling function2. In that case, you need some kind of extra context, e.g.
class Context
{
friend Function1, Function2, Function3;
enum State
{
f0, f1, f2, f3
} state;
public:
Context() { state = f0; }
~Context() { if (state != f3) { ... may need to do stuff... }
}
void Function1(Context &ctxt)
{
assert(ctxt.state == f0);
ctxt.state = f1;
...
}
void Function2(Context &ctxt)
{
assert(ctxt.state == f1);
ctxt.state = f2;
...
}
void Function3(Context &ctxt)
{
assert(ctxt.state == f2);
ctxt.state = f3;
...
}
int main()
{
Context c;
Function1(c);
...
Function2(c);
...
Function3(c);
// c will be destroyed and check that state is f3.
}
One hack you can try is to have function_1() return a type that only it can construct and then use this as a parameter to function_2()
class created_by_function_1 {
created_by_function_1() { /* private constructor */ }
friend created_by_function_1 function_1();
};
created_by_function_1 function_1() {
// do stuff
return created_by_function_1();
}
void function_2(created_by_function_1) {
}
Now you can only use function_2 if you first called function_1.
auto proof = function_1();
function_2(proof); // OK
function_2(created_by_function_1()); // Compilation error
I would advise against using this :)
// Filter.h/cpp
class Filter
{
public:
int readInt(int* value)
{
if (value == NULL)
return 0;
*value = 15; // some logical;
return 1;
}
};
// TestTee.h/.cpp
class TestTee
{
public:
Func1(Filter* f)
{
...
int val;
f->readInt(&val);
...
}
}
Now, I need to test TestTee class, so I mock the class Filter
class MockFilter : public Filter
{
public:
MOCK_METHOD1(readInt, int(int*));
};
how to write the test case?
TEST_F(TestClass, Test1)
{
TestTee t;
MockFilter filter;
EXPECT_CALL(filter, readInt(_)).Times(1); // failed error: The mock function has no default action set, and its return type has no default value set." thrown in the test body.
/*
int val;
EXPECT_CALL(filter, readInt(&val)).Times(1);
Failed with the following error:
Expected: to be called once
Actual: never called - unsatisfied and active
*/
t.Func1(&filter);
}
So, my problem is
I don't know how to control the output parameters of a function which will be called in my testee function code.
Any comment? thx a lot.
First of all, don't forget that a function needs to be virtual for GoogleMock to be able to actually mock it:
class Filter
{
public:
virtual int readInt(int* value)
{
if (value == NULL)
return 0;
*value = 15; // some logical;
return 1;
}
};
The testing code depends on what you actually want to test. If you want just to ensure that Filter::readInt is called this should be enough:
TEST_F(TestClass, Test1)
{
TestTee t;
MockFilter filter;
EXPECT_CALL(filter, readInt(_));
t.Func1(&filter);
}
(Since readInt has built-in return type (int) GoogleMock should be able to figure out default return value without complaining)
If you want to ensure that readInt is called for example only once, use Times clause:
EXPECT_CALL(filter, readInt(_)).Times(1);
If you want the code of Testee following the readInt call to get adequate return values during test, i.e. if you want a mock to imitate returning values of real function, use Return clause for return value, and SetArgPointee clause for output value passed by pointer, or both like this:
EXPECT_CALL(filter, readInt(_)).WillOnce(DoAll(SetArgPointee<0>(15), Return(1)));