Mocking free function
No it's not possible, without changing the sources, or bringing your own version of foo()
that is linked with the executable code.
From GoogleMock's FAQ it says
My code calls a static/global function. Can I mock it?
You can, but you need to make some changes.In general, if you find yourself needing to mock a static function, it's a sign that your modules are too tightly coupled (and less flexible, less reusable, less testable, etc). You are probably better off defining a small interface and call the function through that interface, which then can be easily mocked. It's a bit of work initially, but usually pays for itself quickly.
This Google Testing Blog post says it excellently. Check it out.
Also from the Cookbook
Mocking Free Functions
It's possible to use Google Mock to mock a free function (i.e. a C-style function or a static method). You just need to rewrite your code to use an interface (abstract class).Instead of calling a free function (say, OpenFile) directly, introduce an interface for it and have a concrete subclass that calls the free function:
class FileInterface {
public:
...
virtual bool Open(const char* path, const char* mode) = 0;
};
class File : public FileInterface {
public:
...
virtual bool Open(const char* path, const char* mode) {
return OpenFile(path, mode);
}
};
Your code should talk to FileInterface to open a file. Now it's easy to mock out the function.
This may seem much hassle, but in practice you often have multiple related functions that you can put in the same interface, so the per-function syntactic overhead will be much lower.
If you are concerned about the performance overhead incurred by virtual functions, and profiling confirms your concern, you can combine this with the recipe for mocking non-virtual methods.
As you mentioned in your comment that you actually provide your own version of foo()
, you can easily solve this having a global instance of another mock class:
struct IFoo {
virtual A* foo() = 0;
virtual ~IFoo() {}
};
struct FooMock : public IFoo {
FooMock() {}
virtual ~FooMock() {}
MOCK_METHOD0(foo, A*());
};
FooMock fooMock;
// Your foo() implementation
A* foo() {
return fooMock.foo();
}
TEST(...) {
EXPECT_CALL(fooMock,foo())
.Times(1)
.WillOnceReturn(new MockA());
// ...
}
Don't forget to clear all call expectations, after each test case run.
Google Mock a free system function on Linux always finishes with memory leak
After some month using the solution of my first answer on several platforms I found that it is not very stable. In particular on MS Windows I had trouble that GoogleMock does not always find the mocking function. So I decided to accept minimal modification of the production code and use a wrapper class for the free system functions as recommended by googletest.
With the following I only have to add a header file to the production code and change its system calls for example
# from
fd = fopen("openclose.txt", "a");
# to
fd = stdioif->fopen("openclose.txt", "a");
On Microsoft Windows I have cloned googletest from github built it using powershell with settings cmake -S . -B build
then cmake --build build --config MinSizeRel
and stay in its root directory using this structure:
├── build
│ └── lib
│ └── MinSizeRel
│ ├── gmock.lib
│ ├── gmock_main.lib
│ ├── gtest.lib
│ └── gtest_main.lib
├── include
│ └── stdioif.h
├── src
│ ├── main.cpp
│ ├── openclose.cpp
│ └── test_openclose.cpp
├── main.exe
├── main.obj
├── openclose.txt
├── test_openclose.exe
└── test_openclose.obj
Here is the header file:
#ifndef INCLUDE_STDIOIF_H
#define INCLUDE_STDIOIF_H
#include <stdio.h>
class Istdio {
// Interface to stdio system calls
public:
virtual ~Istdio() {}
virtual FILE* fopen(const char* pathname, const char* mode) = 0;
virtual int fprintf(FILE* stream, const char* format) = 0;
virtual int fclose(FILE* stream) = 0;
};
// Global pointer to the current object (real or mocked), will be set by the
// constructor of the respective object.
Istdio* stdioif;
class Cstdio : public Istdio {
// Real class to call the system functions.
public:
virtual ~Cstdio() {}
// With the constructor initialize the pointer to the interface that may be
// overwritten to point to a mock object instead.
Cstdio() { stdioif = this; }
FILE* fopen(const char* pathname, const char* mode) override {
return ::fopen(pathname, mode);
}
int fprintf(FILE* stream, const char* format) override {
return ::fprintf(stream, format);
}
int fclose(FILE* stream) override {
}
};
// This is the instance to call the system functions. This object is called
// with its pointer stdioif (see above) that is initialzed with the
// constructor. That pointer can be overwritten to point to a mock object
// instead.
Cstdio stdioObj;
/*
* In the production code you must call it with, e.g.:
stdioif->fopen(...)
* The following class should be coppied to the test source. It is not a good
* idea to move it here to the header. It uses googletest macros and you always
* hove to compile the code with googletest even for production and not used.
class Mock_stdio : public Istdio {
// Class to mock the free system functions.
public:
virtual ~Mock_stdio() {}
Mock_stdio() { stdioif = this; }
MOCK_METHOD(FILE*, fopen, (const char* pathname, const char* mode), (override));
MOCK_METHOD(int, fprintf, (FILE* stream, const char* format), (override));
MOCK_METHOD(int, fclose, (FILE* stream), (override));
};
* In a gtest you will instantiate the Mock class, prefered as protected member
* variable for the whole testsuite:
Mock_stdio mocked_stdio;
* and call it with: mocked_stdio.fopen(...) (prefered)
* or stdioif->fopen(...)
*/
#endif // INCLUDE_STDIOIF_H
This is the simple example program:
#include "stdioif.h"
#include <iostream>
int openclose() {
FILE* fd = nullptr;
int rc = 0;
fd = stdioif->fopen("openclose.txt", "a");
if(fd == NULL) {
std::cerr << "Error opening file\n";
return 1;
}
rc = stdioif->fprintf(fd, "hello world :-)\n");
if(rc < 0) {
std::cerr << "Error appending to file with return code: " << rc << "\n";
stdioif->fclose(fd);
return rc;
}
rc = stdioif->fclose(fd);
if(rc) {
std::cerr << "Error closing file with return code: " << rc << "\n";
return rc;
}
std::cout << "done.\n";
return 0;
}
I execute it with:
#include "src/openclose.cpp"
int main() {
return openclose();
The test program looks like this:
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "stdioif.h"
#include "src/openclose.cpp"
using ::testing::_;
using ::testing::Return;
class Mock_stdio : public Istdio {
// Class to mock the free system functions.
public:
virtual ~Mock_stdio() {}
Mock_stdio() { stdioif = this; }
MOCK_METHOD(FILE*, fopen, (const char* pathname, const char* mode), (override));
MOCK_METHOD(int, fprintf, (FILE* stream, const char* format), (override));
MOCK_METHOD(int, fclose, (FILE* stream), (override));
};
class OpenCloseTestSuite: public ::testing::Test {
protected:
// Member variables of the whole testsuite: instantiate the mock objects.
Mock_stdio mocked_stdio;
};
TEST_F(OpenCloseTestSuite, open_close) {
EXPECT_CALL(mocked_stdio, fopen(_, _))
.WillOnce(Return((FILE*)0x123456abcdef));
EXPECT_CALL(mocked_stdio, fprintf(_,_))
.WillOnce(Return(-1));
EXPECT_CALL(mocked_stdio, fclose(_)).Times(1);
// process unit
EXPECT_EQ(openclose(), 0);
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
To compile it on Microsoft Windows I use:
cl -nologo /EHsc -I. -I.\include -I.\googletest\include -I.\googlemock\include .\build\lib\MinSizeRel\gtest.lib .\build\lib\MinSizeRel\gmock.lib .\src\[main.cpp | test_openclose.cpp]
How to mock a free function in python?
This is a perfectly fine way to do it. As long as you know that BlissLiesHere
does not change the overall behavior of the unit you are testing...
EDIT:
This is what is being done, under all the nice extras they provide, by different kinds of mocking libraries, such as Mock, Mox, etc.
How to mock system call in C++ Unit Testing during runtime using GoogleMock?
You can refer to mocking-free-functions in Gmock's documentation.
Unfortunately, using the recommended method means you will have to change your code, which may not work if your code need to strictly be a C
code.
However, if you are willing to accept this, based on the documentation, you will have to create a wrapper around all the system functions that you are using and then mock that wrapper.
Also, don't forget that you will have to add EXPECT_CALL
or ON_CALL
for all functions that are expected to be called and return a non-default (i.e. 0) value. For example, in your first test, you should also provide EXPECT_CALL
or ON_CALL
for fopen
.
Here is an example implementation:
// System wrapper interface class.
class MySystemWrapperInterface {
public:
virtual FILE* fopen(const char* filename, const char* mode) = 0;
virtual int fseek(FILE* stream, long int offset, int whence) = 0;
virtual size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream) = 0;
virtual int ferror(FILE* stream) = 0;
virtual int fclose(FILE* stream) = 0;
};
// System wrapper actual class used in production code.
class MySystemWrapperClass : public MySystemWrapperInterface {
public:
FILE* fopen(const char* filename, const char* mode) {
return ::fopen(filename, mode);
}
int fseek(FILE* stream, long int offset, int whence) {
return ::fseek(stream, offset, whence);
}
size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream) {
return ::fread(ptr, size, nmemb, stream);
}
int ferror(FILE* stream) { return ::ferror(stream); }
int fclose(FILE* stream) { return ::fclose(stream); }
};
// Mocked System wrapper used for testint.
class MySystemWrapperMockClass : public MySystemWrapperInterface {
public:
MOCK_METHOD(FILE*, fopen, (const char*, const char*), (override));
MOCK_METHOD(int, fseek, (FILE*, long int, int), (override));
MOCK_METHOD(size_t, fread, (void*, size_t, size_t, FILE*), (override));
MOCK_METHOD(int, ferror, (FILE*), (override));
MOCK_METHOD(int, fclose, (FILE*), (override));
};
// Wrapper class for your own readdata function.
class MyClass {
// The system wrapper passed by dependency injection through constructor.
MySystemWrapperInterface* system_wrapper_;
public:
// Initialize the system wrapper in constructor.
MyClass(MySystemWrapperInterface* system_wrapper)
: system_wrapper_(system_wrapper) {}
int readdata(void* data, int size, int offset, char* filename) {
if (data == NULL || size == 0 || filename == NULL) {
return -1;
}
FILE* fp = system_wrapper_->fopen(filename, "rb");
if (fp == NULL) {
return -1;
}
if (system_wrapper_->fseek(fp, offset, SEEK_SET) != 0) {
system_wrapper_->fclose(fp);
return -1;
}
system_wrapper_->fread(data, size, 1, fp);
if (system_wrapper_->ferror(fp)) {
system_wrapper_->fclose(fp);
return -1;
}
system_wrapper_->fclose(fp);
return 1;
}
};
TEST(test, Test1fseek) {
// Create the mock object and inject it into your class.
MySystemWrapperMockClass mock_system_wrapper;
MyClass my_object(&mock_system_wrapper);
// When fseek called in readdata API call mock fseek to hit fseek fail
// fseek(){return -1;}
// IMPORTANT: Don't forget to add EXPECT_CALL or ON_CALL for all functions
// that are expected to be called.
EXPECT_CALL(mock_system_wrapper, fopen)
.Times(1)
.WillOnce(Return(reinterpret_cast<FILE*>(0x1)));
EXPECT_CALL(mock_system_wrapper, fseek).Times(1).WillOnce(Return(1));
EXPECT_CALL(mock_system_wrapper, fclose).Times(1).WillOnce(Return(1));
char data[10] = {0};
int status = my_object.readdata(data, sizeof(data), 0, "test.txt");
EXPECT_EQ(status, -1);
}
TEST(test, Test2fread) {
// Create the mock object and inject it into your class.
MySystemWrapperMockClass mock_system_wrapper;
MyClass my_object(&mock_system_wrapper);
// When fread called in readdata API call mock fread to hit read fail
// fread(){return -1;}
// IMPORTANT: Don't forget to add EXPECT_CALL or ON_CALL for all functions
// that are expected to be called.
EXPECT_CALL(mock_system_wrapper, fopen)
.Times(1)
.WillOnce(Return(reinterpret_cast<FILE*>(0x1)));
EXPECT_CALL(mock_system_wrapper, fseek).Times(1).WillOnce(Return(0));
EXPECT_CALL(mock_system_wrapper, fread).Times(1).WillOnce(Return(-1));
EXPECT_CALL(mock_system_wrapper, ferror).Times(1).WillOnce(Return(-1));
EXPECT_CALL(mock_system_wrapper, fclose).Times(1).WillOnce(Return(1));
char data[10] = {0};
int status = my_object.readdata(data, sizeof(data), 0, "test.txt");
EXPECT_EQ(status, -1);
}
Live example: https://godbolt.org/z/qxf74fWGh
Related Topics
May I Take the Address of the One-Past-The-End Element of an Array
Access Variable Value Using String Representing Variable's Name in C++
Using Regex Lookbehinds in C++11
One VS2010 Bug ? Allowing Binding Non-Const Reference to Rvalue Without Even a Warning
Is Auto as a Parameter in a Regular Function a Gcc 4.9 Extension
Using Float Gives "Call to Overloaded Function Is Ambiguous" Error
What Is the Purpose of Allocating a Specific Amount of Memory for Arrays in C++
Why Does Gcc Compiler Output Pow(10,2) as 99 Not 100
Should We Pass a Shared_Ptr by Reference or by Value
Best Documentation for Boost:Asio
C++ Auto Keyword. Why Is It Magic
What Does 'Const Static' Mean in C and C++
C++ Warning: Deprecated Conversion from String Constant to 'Char*' [-Wwrite-Strings]
Replacement for Deprecated Register Keyword C++ 11
How to Read the Results of a System() Call in C++