I have mocked function like:
virtual void MyClass::foo(const std::function<void()>& callback);
I want to set expectation for foo:
EXPECT_CALL(MyClassMock, foo(testing::_));
and then I want to call received callback when expectation is fulfilled.
How to do that using gmock?
Option #1
EXPECT_CALL(MyClassMock, foo(testing::_))
.Times(1)
.WillOnce(testing::InvokeArgument<0>());
Option #2
EXPECT_CALL(MyClassMock, foo(testing::_))
.Times(1)
.WillOnce(testing::Invoke([](std::function<void()> f){f();}));
I have not tested this but the principle should get you there.
Change your EXPECT_CALL to repeatedly invoke a function. This function should be global/static, probably located in the same file as your expectations. Invoke automatically forwards the arguments so the parameter list should match.
EXPECT_CALL(MyClassMock, foo(testing::_))
.WillRepeatedly(Invoke(myCallbackFunc));
...
static void myCallbackFunc(const std::function<void()>& callback)
{
callback();
}
More ways of invoking functions after an EXPECT can be seen on the GoogleMock Cheat Sheet.
Related
In Google Mock, is there any inverse of InSequence? E.g. OutOfSequence
E.g. the assertion only works if the correct sequence does NOT occur.
AFAIK, there is not a feature like that which you can use directly, however, it's not hard to get to what you want.
Say you want the test fail if the following sequence of calls happen:
Disconnect() -> Connect()
You ask EXPECT_CALL to register the call sequences in a vector and then you can check to see if the sequence vector is what you expected. You can do this using Invoke, by using WillOnce and a lambda function that gets invoked when the function is called.
Here is an example that checks if Disconnect() -> Connect() sequence does not happen.
using ::testing::ElementsAre;
using ::testing::Not;
// Test if two functions are called out of sequence.
TEST(AtmMachine, OutOfSequence) {
std::vector<std::string> sequenceVector;
// Arrange
MockBankServer mock_bankserver;
// Assuming we want the test fail if Disconnect happens before Connect.
// We store their sequence in sequenceVector.
EXPECT_CALL(mock_bankserver, Disconnect())
.Times(1)
.WillOnce(
[&sequenceVector]() { sequenceVector.push_back("Disconnect"); });
EXPECT_CALL(mock_bankserver, Connect())
.Times(1)
.WillOnce([&sequenceVector]() { sequenceVector.push_back("Connect"); });
// Act
AtmMachine atm_machine(&mock_bankserver);
atm_machine.Withdraw(1234, 1000);
// Assert that the Disconnect() -> Connect() does not happen
EXPECT_THAT(sequenceVector, Not(ElementsAre("Disconnect", "Connect")));
}
Suppose I have a method and I want to test it using gtest/gmock framework. This method calls another method inside itself using a Qt queued invoke:
void MyClass::handleFoo()
{
// ...
Q_ASSERT(QMetaObject::invokeMethod(this, "handleBar", Qt::QueuedConnection));
}
void MyClass::handleBar()
{
_view.show();
}
TEST_F(MyTestSuite, MyTest)
{
EXPECT_CALL(_viewMock, show()); // Fails with never called
emit _myClassObj->foo();
// Tried QCoreApplication::processEvents() -- does not help
}
Is there any way to do it? I think maybe I should just test these two handlers separately. But how can I test that the method handleFoo() will indeed call handleBar()?
I am trying to use marvinroger/async-mqtt-client that in the provided examples is used together with freertos timers that use a callback that gets invoked whenever the timer expire. The full example is here.
I wanted to create a singleton class to enclose all the connection managing part and just expose the constructor (through a getInstance) and a begin function that other than setting the callbacks, creates the timers for reconnection.
The class looks like (I simplified by removing useless parts):
class MqttManager : public Singleton<MqttManager> {
public:
virtual ~MqttManager() = default;
void begin();
protected:
MqttManager();
void connectToMqtt(TimerHandle_t xTimer);
void WiFiEvent(WiFiEvent_t event);
void onConnect(bool sessionPresent);
std::unique_ptr<AsyncMqttClient> client;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;
};
While my issue is when I try to pass the connectToMqtt callback to the timer.
MqttManager::MqttManager() {
this->client = std::unique_ptr<AsyncMqttClient>(new AsyncMqttClient());
// use bind to use a class non-static method as a callback
// (works fine for mqtt callbacks and wifi callback)
this->client->onConnect(std::bind(&MqttManager::onConnect, this, std::placeholders::_1));
WiFi.onEvent(std::bind(&MqttManager::WiFiEvent, this, std::placeholders::_1));
// Here it fails
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)nullptr, &MqttManager::connectToMqtt, this, std::placeholders::_1);
The error is:
cannot convert 'void (MqttManager::)(TimerHandle_t) {aka void (MqttManager::)(void*)}' to 'TimerCallbackFunction_t {aka void ()(void)}' for argument '5' to 'void* xTimerCreate(const char*, TickType_t, UBaseType_t, void*, TimerCallbackFunction_t)'
Now, from here, having in mind that the problem is around having a pointer to a non-static method that needs somehow to be casted to a free function pointer, three doubts arise:
Why on earth the std::bind "approach" works for WiFi.onEvent but not for xTimerCreate? They seem pretty similar to me... WiFi is typedef void (*WiFiEventCb)(system_event_id_t event); while the timer typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );
How can I make this work? Is there a cast or a better approach?
Is this bad practice? My goal here was to enclose mqtt and wifi functions and callbacks in a neat class easily recognizable, organized and maintainable; but I guess that sometimes you just obtain the opposite result without noticing...
FreeRTOS code is plain old C. It knows nothing about C++, instance methods, function objects, etc. It takes a pointer to a function, period. As Armandas pointed out, WiFi.onEvent on the other hand is C++, lovingly written by someone to accept output from std::bind().
There is a workaround. When you read the xTimerCreate API docs, there is a sneaky little parameter pvTimerID which is effectively user-specified data. You can use this to pass a pointer to your class and later retrieve it from inside the callback function using pvTimerGetTimerID(). With a class pointer you can then forward the callback to your C++ class. See example below.
It's good practice to try to hide private class methods and data. Unfortunately this only works well if you're working entirely in C++ :) If calling into C libraries (like FreeRTOS) I find myself breaking such idealistic principles occasionally.
Here's how I'd do it. I use a lambda (without context) as the actual callback function because it's throwaway wrapper code, and the C libraries happily accept it as a plain old function pointer.
auto onTimer = [](TimerHandle_t hTmr) {
MqttManager* mm = static_cast<MqttManager*>(pvTimerGetTimerID(hTmr)); // Retrieve the pointer to class
assert(mm); // Sanity check
mm->connectToMqtt(hTmr); // Forward to the real callback
}
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, static_cast<void*>(this), onTimer);
std::bind returns a callable object, not a function pointer. It works with WiFi.onEvent because there is an overload taking a std::function:
typedef std::function<void(arduino_event_id_t event, arduino_event_info_t info)> WiFiEventFuncCb;
// ...
wifi_event_id_t onEvent(WiFiEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX);
Solution
Create a static function for the timer callback and simply get the MqttManager instance as you would from anywhere else.
I want to not call a few function calls that are inside a function that I am testing. I am new to testing. Since I am using SetUpALL((){}); to create a test suitable case instead of using the function.
main file:
class A{
Future<void> function_1 () async {
await another_function_1 // want to igonre this function in test.
}
}
test file:
void main {
setUpAll((){
// statements.
});
group('tests',(
test('test 1',(){
A().function1(); // calling the function here for testing.
});
){
});
}
Welcome to the world of "Designing Testable Classes". You'll probably need to refactor this method to extract a testable part of the operations. Also, learn about Mockito to stub out dependent classes with your own behavior.
I am currently trying to implement a messenger system for my game engine. It uses function callbacks of the form:
typedef std::function<void(const Message &)> Callback;
I want all objects to be able to subscribe to a message of a specific type (where the type is just a string). Subscribing means adding their "onEvent" function to the dictionary of callbacks.
mutable std::map<std::string, std::vector<Callback>> callbackDictionary;
The update function then calls these functions and passes the according message (from which the "onEvent" functions can get their data)
for each (auto message in messageList)
{
// find the list of respective callbacks
auto it = callbackDictionary.find(message->GetType());
// If there are callbacks registered for this message type
if (it != callbackDictionary.end())
{
// call every registred callback with the appropreate message
for each (auto callback in it->second)
callback(*message);
}
}
Now, my problem is that I am not quite sure how to bind these "onEvent" functions. I have just recently switched to C++11 and the concept of function objects and std::bind is quite new to me. So here is what I have tried:
messageBus.Subscribe("Message/Click",std::bind(&ClickableComponent::OnClick, this));
where the ClickableComponent::OnClick function has the required signature:
void OnClick(const Message &);
and the Subscribe function just adds the passed function to the dictionary
void Messenger::Subscribe(std::string type, Callback callbackFunction) const
{
callbackDictionary[type].push_back(callbackFunction);
}
(The push_back is used because there is a vector of callbacks for each type)
The code seems fine to me but the line:
messageBus.Subscribe("Message/Click", std::bind(&ClickableComponent::OnClick, this));
Gives me the error:
picture of the error discription
I have tried all kinds of stuff like forwarding the Messenger reference and using placeholders, but I have the feeling that I am doing something else wrong. Also, better idea on how to implement this messenger system are appreciated ^^
Thanks for your help!
std::bind is not necessary in your case, lambda function would do just fine:
messageBus.Subscribe("Message/Click", [this](const Message& msg) { OnClick(msg); });
std::bind is more useful in specific cases of metaprogramming.
But if you're curios enough to see how to use std::bind:
messageBus.Subscribe("Message/Click",
std::bind(&ClickableComponent::OnClick, this, std::placeholders::_1));
Here, as you see, you missed std::placeholders::_1. Your functor signature is void(const Message&), but you try to store a member function which signature can be regarded as void(ClickableComponent*, const Message&). To partially apply some arguments (what std::bind does) you need to specify arguments that you'd like to bind and arguments that you leave unbound.
Lambda is preferred because usually it's shorted, more flexible and more readable.