5

New to cpp (Java guy).

I have 3rd party library that has method sendMail(txt). I don't want to test the library. i want to test my own method, so in order to do this , i need to mock the library calls .

My own method is looking like this:

#include "mailsender.h"

int run(txt){
    analysis(txt);
    ...
    ...
    int status =  sendMail(txt);//sendMail is a 3rd party library call. i need to mock it.its not part of the unit test
    return status;
}

In Java the mailsender was interface and it was injected to my class, so in case of test i inject mock. What is a good practice in cpp to mock library calls? I can wrap the 3rd party library call in a class and inject this class, but i am looking for something simpler and for the common practice (maybe ifndf).

I am familiar with googlemock. googlemock allow me to mock classes . i am not aware to option how to mock a call in my tested method.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
Avihai Marchiano
  • 3,837
  • 3
  • 38
  • 55
  • can you improve your example of what you want to do? – BЈовић Jul 27 '12 at 11:34
  • See at code.google.com/p/googlemock/ - google mock framework. – Torsten Jul 27 '12 at 11:36
  • 1
    Create your own library with your mocked classes and link to that one instead of the real lib. – RedX Jul 27 '12 at 12:13
  • RedX,it's an option. The disadvantage is the overhead of creating library and test need to be in a separate project – Avihai Marchiano Jul 27 '12 at 12:16
  • Since you will have to mock the function calls anyway you are not writing (much) more code. I agree on the separation question though. – RedX Jul 27 '12 at 12:19
  • 1
    It doesn't have to be in a separate project, you can create a different build (eg Debug, Release, Test) with appropriate macros that add/remove certain parts using #ifdefs. – gbjbaanb Jul 27 '12 at 12:21

4 Answers4

5

So I assume you have a 'global' function that is implemented in a library that you both include a header file for (to get the definition) and link (to get the implementation).

You obviously need to replace the implementation of the library with your own - one that does "nothing", so you can do this in 2 ways:

  • you replace the .dll (or .so) with your own implementation that has all the methods the 3rd party library exposes. This is easy once you've written a new version of all the 3rd party lib functions, but writing them all out can be a pain.
  • you remove the library temporarily, and replace the calls you make to that in a .cpp source file that implements those functions. So you'd create your own sendMail() function in a .cpp file and include this into the program instead of the mailsender.h include.

The latter is easier, but you might also have to modify your program to not link with the 3rd party lib. This can also require changing the #include as well, as some compilers (eg VC++) allow you to embed linker directives in the source. If your does this, then you won't be able to stop the linker from including the 3rd party lib.

The other option is to modify your code to use a different call to the sendMail call, eg test__sendMail() that you implement yourself. Wrap this is a macro to conditionally include your, or the real, function call depending on your build options.

If this was a c++ library then you'd probably be able to use a mocking framework like you're used to, but it sounds like its a C library, and they simply provide a list of functions that you use directly in your code. You could wrap the library in your own class and use that instead of calling the 3rd party lib functions directly.

There is a list of C mocking frameworks.

Community
  • 1
  • 1
gbjbaanb
  • 51,617
  • 12
  • 104
  • 148
  • I think I will go with macro . What is your favorite pattern? – Avihai Marchiano Jul 27 '12 at 12:26
  • My favourite pattern is the Big Ball of Mud. I'm not a huge fan of unit testing as most people think of it - but I do a lot of integration tests instead, usually having a config option at the start of some methods that access external services (eg like your mail server) that just log the data input, then I can test the rest of the system to make sure that the desired mail is generated and eventually sent to that method. – gbjbaanb Jul 27 '12 at 15:24
  • 1
    Interesting. I also think too that unit test are over rated and integration test is important than unit test. Unit test should be like guards. We need to place them in volarable places and not on any method. In this case this method is quite complex andi need to be able to test it without the need in network, which required by the 3rd party library. It's nice to see that there are still people that don't adopt unit test like new religious – Avihai Marchiano Jul 27 '12 at 19:39
4

Disclaimer: I wrote ELFspy.

Using ELFspy, the following code will allow you to fake/mock the sendMail function by replacing it with an alternative implementation.

void yourSendMail(const char* txt) // ensure same signature as sendMail
{
  // your mocking code
}

int main(int argc, char** argv)
{
  spy::initialise(argc, argv);
  auto sendMail_hook = SPY(&sendMail); // grab a hook to sendMail
  // use hook to reroute all program calls to sendMail to yourSendMail
  auto sendMail_fake = spy::fake(sendMail_hook, &yourSendMail);
  // call run here..
}

Your program must be compiled with position independent code (built with shared libraries) to achieve this.

Further examples are here: https://github.com/mollismerx/elfspy/wiki

2

This is an old question, with an already choosen response, but maybe the following contribution can help someone else.

First solution

You still have to create a custom library to redefine the functions, but you do not need to change Makefiles to link to your "fake-library", just use LD_PRELOAD with the path to the fake-library and that will be the first that the linker will find and then use.

example

Second solution

ld (GNU) linker has an option --wrap that let you wrap only one function with another provided by the user. This way you do not have to create a new library/class just to mock the behavior

Here is the example from the man page

--wrap=symbol Use a wrapper function for symbol. Any undefined reference to symbol will be resolved to "__wrap_ symbol ". Any undefined reference to "__real_ symbol " will be resolved to symbol.

This can be used to provide a wrapper for a system function. The wrapper function should be called "__wrap_ symbol ". If it wishes to call the system function, it should call "__real_ symbol ".

Here is a trivial example:

void *
__wrap_malloc (size_t c)
{
  printf ("malloc called with %zu\n", c);
  return __real_malloc (c);
}

If you link other code with this file using --wrap malloc, then all calls to "malloc" will call the function "__wrap_malloc" instead. The call to "__real_malloc" in "__wrap_malloc" will call the real "malloc" function.

You may wish to provide a "__real_malloc" function as well, so that links without the --wrap option will succeed. If you do this, you should not put the definition of "__real_malloc" in the same file as "__wrap_malloc"; if you do, the assembler may resolve the call before the linker has a chance to wrap it to "malloc".

Carlo Lobrano
  • 368
  • 1
  • 9
0

Though there is no interface keyword, you can use Abstract Base Classes for similar things in C++.

If the library you are using doesn't come with such abstractions, you can wrap it behind your own "interface". If your code separates construction of objects from usage (e.g. by IoC), you can either use this to inject a fake or use Mocks:

https://stackoverflow.com/questions/38493/are-there-any-good-c-mock-object-frameworks

Community
  • 1
  • 1
Philipp
  • 11,549
  • 8
  • 66
  • 126