Contents
This package wraps Mock Objects for a service server, a message subscriber and a actionlib server.
Creating a Mock Object
First include the code dependencies and add to your code the following include files
#include "ros/ros.h" #include "gtest/gtest.h" #include "mock_objects/MockSubscriber.h"
To create a mock subscriber
typedef controllersAndSensors_communications::irMsg ir; MockSubscriber<ir> irSubscriber;
Creating a mock action server can be done as in this example:
#include "ros/ros.h"
#include "mock_objects/MockActionServer.h"
#include "RoboticArm_communications/moveArmAction.h"
MOCK_ACTION_SERVER(hello,RoboticArm_communications::moveArm)
int main() {
        MockhelloActionServer a("test");
}
Range Checks using mock objects
You can use the mock objects for performing range checks, using the build in google mock functions. For a message with the definition
Header header int32[5] distance
the following range check can be defined:
EXPECT_CALL(irSubscriber, subscriberActualCallback( Pointee(Field(&ir::distance, ElementsAre( AnyOf(IsBetween(0, 800), Eq(-1)), AnyOf(IsBetween(0, 300), Eq(-1)), AnyOf(IsBetween(0, 300), Eq(-1)), AnyOf(IsBetween(0, 800), Eq(-1)), AnyOf(IsBetween(40, 300), Eq(-1)))) ))).Times(AtLeast(0));
where the IsBetween is a matcher defined as follows:
MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is")
+ " between " + PrintToString(a) + " and " + PrintToString(b)) {
  return a <=arg;
}Note that you need to add the following lines too
using ::testing::AtLeast; using ::testing::Eq; using ::testing::AllOf; using ::testing::Field; using ::testing::Pointee; using ::testing::PrintToString; using ::testing::ElementsAre; using ::testing::Matcher; using ::testing::AnyOf;
Complex Logical Rules
Combining the Google Mock AnyOf and AllOf matchers can provide more complex rules for range checks. For example:
EXPECT_CALL(soundExistenceSubscriber, subscriberActualCallback(
  AllOf(
    AnyOf(
      Pointee(Field(&existenceMsg::soundExists, Eq(0))),
      Pointee(Field(&existenceMsg::soundExists, Eq(1)))
    ),
    Pointee(Field(&existenceMsg::certainty, IsBetween(0,1)))
))).Times(AtLeast(0)); and a simple or-like statement
EXPECT_CALL(lineColorSubscriber, subscriberActualCallback(
   AnyOf(
     AllOf(
        Pointee(Field(&lineMsg::orientation, Eq(1))),
        Pointee(Field(&lineMsg::fromAngle, IsBetween(-XCAM,XCAM))),
        Pointee(Field(&lineMsg::toAngle, IsBetween(-XCAM, XCAM))),
        Pointee(Field(&lineMsg::color, IsBetween(1,4)))),
     AllOf(
        Pointee(Field(&lineMsg::orientation, Eq(2))),
        Pointee(Field(&lineMsg::fromAngle, IsBetween(-YCAM, YCAM))),
        Pointee(Field(&lineMsg::toAngle, IsBetween(-YCAM, YCAM))),
        Pointee(Field(&lineMsg::color, IsBetween(1,4))))
))).Times(AtLeast(0));
Define New Matchers
You can define new matchers to simplify rules. For example, checking a message that has x,y,z that all messages fall into a sphere of a specific distance, we first define a matcher:
MATCHER_P(DistanceIsLess, distance, "") {
  return arg.x*arg.x+arg.y*arg.y+arg.z*arg.z < distance * distance;
}and then use it.
TF matcher
A matcher for the tf is as follows
MATCHER_P8(tfLimit, frame, childFrame, minX, maxX, minY, maxY, minZ, maxZ, std::string(negation ? "isn't" : "is")
+ " between " + PrintToString(minX) + " and " + PrintToString(maxX)) {
  bool xInLimit = arg.transform.translation.x >= minX && 
         arg.transform.translation.x <= maxX;
  bool yInLimit = arg.transform.translation.y >= minY && 
         arg.transform.translation.y <= maxY;
  bool zInLimit = arg.transform.translation.z >= minZ && 
         arg.transform.translation.y <= maxZ;
  bool correctFrames = (frame == arg.header.frame_id) && 
        (childFrame == arg.child_frame_id);
  if (correctFrames)
    return xInLimit && yInLimit && zInLimit;
  return 1;
}
More Examples
You can find more examples in the RangeTests package and at the googlemock documentation.