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.
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();
}
};
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.
I know EXPECT_CALL is supposed to be used for mocked classes and their objects/methods. But is it ever possible to use this to expect calls of local methods?
void Sample::Init()
{
// some codes here...
auto enabled = isFeatureEnabled();
//some other things here
}
bool Sample::isFeatureEnabled()
{
return lights_ and sounds_;
}
I want to EXPECT_CALL isFeatureEnabled() - is this at all possible?
You can try this, I find this approach useful:
class template_method_base {
public:
void execute(std::string s1, std::string s2) {
delegate(s1 + s2);
}
private:
virtual void delegate(std::string s) = 0;
};
class template_method_testable : public template_method_base {
public:
MOCK_METHOD1(delegate, void(std::string s));
};
TEST(TestingTemplateMethod, shouldDelegateCallFromExecute) {
template_method_testable testable_obj{};
EXPECT_CALL(testable_obj, delegate("AB"));
testable_obj.execute("A", "B");
}
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 am newer for google mock. Now I have one question about how to match the argument reference? here are the codes
class Parameter {
public:
int m_idata;
char m_cdata;
bool Parameter::operator ==(const Parameter& element) const {
return (m_idata == element.m_idata && m_cdata == element.m_cdata);
}
};
class FooInterface {
public:
virtual ~FooInterface() {}
virtual void SetParameter(Parameter& val) = 0;
};
// mock class
class MockFoo: public FooInterface {
public:
MOCK_METHOD1(SetParameter, void(Parameter& val));
};
TEST(FooTest, setParameterTest) {
MockFoo mockFoo;
EXPECT_CALL(mockFoo, SetParameter(An<Parameter&>())); // How to match argument reference???
Parameter para;
mockFoo.SetParameter(para); // there is an exception here, why???
}
and I also tried the following to match SetParameter():
Parameter test_para;
EXPECT_CALL(mockFoo, SetParameter(Ref(test_para)));
And
EXPECT_CALL(mockFoo, SetParameter(A<Parameter&>()));
And
Parameter test_para;
test_para.m_cdata = 'c';
test_para.m_idata = 10;
EXPECT_CALL(mockFoo, SetParameter(_)).WillOnce(::testing::SetArgReferee<0>(test_para));
Both those two codes can also cause exception...
Could any one tell me how to match the argument reference Parameter& in the function SetParameter()?
This was supposed to be a comment, but I don't have enough reputation.
The only error in your code is that you have a superfluous "Parameter::".
I tried to run the code and I didn't see any exception. It ran just fine.