Giter VIP home page Giter VIP logo

gmock-global's Introduction

gmock-global Build Status

This header-only library implements gmock functionality for global functions.

Introduction

Gmock is a C++ framework for writing mock classes. It is very convenient to create mock objects for mocking of methods. But gmock can not mock global functions. This problem is quite common but has no trivial solution. Gmock FAQ says you are doing something wrong if you need to mock static or global functions. However it is required in some cases and gmock-global provides such functionality.

Usage

Step 1: Adding includes

At first your project needs to know about gmock-global.

  1. Add gmock-global/include to the project include paths.
  2. Add #include <gmock-global/gmock-global.h> after gmock include.

Step 2: Declare mock global

Syntax is most similar to gmock. For example, to mock function multiply with two double arguments and double result you have to write declaration:

MOCK_GLOBAL_FUNC2(multiply, double(double, double));

You can check call count of such function using EXPECT_GLOBAL_CALL macro, same as you used EXPECT_CALL macro for classes:

EXPECT_GLOBAL_CALL(multiply, multiply(1, 2));

The .Times(...) and other methods will be work too.

In result mocking of global double multiply(double, double) looks like:

MOCK_GLOBAL_FUNC2(multiply, double(double, double));

...

TEST(TestGlobal, CanMultiplyGlobal)
{
    EXPECT_GLOBAL_CALL(multiply, multiply(1, 2)).Times(1);
    multiply(1, 2);
}

Also you can use ON_GLOBAL_CALL to specify default behavior. ON_GLOBAL_NICE_CALL can be used to set default behavior with suppressed warning when this mock was actually called.

gmock-global supports more than 10 arguments with gtest version 1.8.1. But it requires gmock-more-args version 1.0.1 in case you use gtest version 1.8.0

Known issues

The after clause can't be using with gmock-global, use Sequences instead.

Samples

Samples live in the separate repository

License

gmock-global is licensed under the MIT License. You can freely use it in your commercial or opensource software.

Version history

Version 1.0.2 (28 Aug 2019)

  • Added ON_GLOBAL_CALL (#4)
  • Segmentation fault when executing tests on a function that has been mocked in another test (#2)

Version 1.0.1 (19 Apr 2019)

  • Specified compatibility with gtest 1.8.1
  • Fixed warnings

Version 1.0.0 (17 Oct 2017)

  • Initial public release

gmock-global's People

Contributors

artek-koltun avatar grivus avatar kurkin avatar mihaigalos avatar sergiusthebest avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gmock-global's Issues

how to recover the funtion?

Hi.
In my unit tests, I mock a function. I want to restore this function to its original form after running my module. What should I do?

Can I tell the global mock what should it return?

In googlemock docs:

  ON_CALL(foo, GetSize())                         // #3
      .WillByDefault(Return(1));

How can I do something similar with mock of free function? There's no ON_GLOBAL_CALL macro or any macro at all, besides MOCK_GLOBAL_FUNC* family and EXPECT_GLOBAL_CALL.

Segmentation fault when executing tests on a function that has been mocked in another test

Before using gmock-global, I had implemented a couple of tests for functions that didn't need mocks. These lower level functions are then called from other higher level functions.

When I try to mock one of the lower level functions, it works great for that but the test case for the lower level function produces a segmentation fault.

I understand that this is because a global mock is global but is there a way I can encapsulate the mock only to the test I want to use the mock?

If not, do you have any recommendations for what I should do?

[----------] 2 tests from lowLevelFunctionTest
[ RUN      ] lowLevelFunctionTest.Same_Size

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff78eae69 in testing::internal::UntypedFunctionMockerBase::SetOwnerAndName(void const*, char const*) () from /googletest/install/lib/libgmock.so
(gdb) bt
#0  0x00007ffff78eae69 in testing::internal::UntypedFunctionMockerBase::SetOwnerAndName(void const*, char const*) () from /googletest/install/lib/libgmock.so
#1  0x0000555555580492 in lowLevelFunction(cv::Mat const&, int, int) ()
#2  0x00005555555a1685 in lowLevelFunctionTest_Same_Size_Test::TestBody() ()
#3  0x00007ffff7ba0aa3 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) () from /googletest/install/lib/libgmock.so
#4  0x00007ffff7b9a867 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) () from /googletest/install/lib/libgmock.so
#5  0x00007ffff7b78df2 in testing::Test::Run() () from /googletest/install/lib/libgmock.so
#6  0x00007ffff7b7974f in testing::TestInfo::Run() () from /googletest/install/lib/libgmock.so
#7  0x00007ffff7b79deb in testing::TestCase::Run() () from /googletest/install/lib/libgmock.so
#8  0x00007ffff7b84cb4 in testing::internal::UnitTestImpl::RunAllTests() () from /googletest/install/lib/libgmock.so
#9  0x00007ffff7ba1c69 in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) ()
   from /googletest/install/lib/libgmock.so
#10 0x00007ffff7b9b6c7 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) ()
   from /googletest/install/lib/libgmock.so
#11 0x00007ffff7b83711 in testing::UnitTest::Run() () from /googletest/install/lib/libgmock.so
#12 0x00005555555728ef in main ()

"warning C4172: returning address of local variable or temporary" under MSVC 2017

Great enhancement to GMock! I was working on the same problem and came across your library, which saved me a bunch of work. Thank you. Unfortunately I was getting the above compiler warning, as well as a runtime error about leaking mocks:

unknown file: ERROR: this mock object should be deleted but never is. Its address is @00558290.
c:\users\chris\workspace\layermockup\dsp\manualidlmockup\communication\client_library\test\clientinterfacegtest.cpp(122): ERROR: this mock object (used in test ClientTest.Mocking) should be deleted but never is. Its address is @94A19829.
ERROR: 2 leaked mock objects found at program exit. Expectations on a mock object is verified when the object is destructed. Leaking a mock means that its expectations aren't verified, which is usually a test bug. If you really intend to leak a mock, you can suppress this error using testing::Mock::AllowLeak(mock_object), or you may use a fake or stub instead of a mock.

I compared the guts of MOCK_GLOBAL_FUNC0_ vs. MOCK_METHOD0_ and discovered that the difference is that MOCK_GLOBAL_FUNC0_ returns a reference:

 ::testing::MockSpec<__VA_ARGS__>&

While MOCK_METHO0_ returns by value. Not sure why - maybe the latest GMock has changed? Or maybe because I'm using VS2017? Under gcc I also get problems:

gmock-global.h:27:52: error: invalid initialization of non-const reference of type ‘testing::internal::MockSpec<void()>&’ from an rvalue of type ‘testing::internal::MockSpec<void()>’
     return GMOCK_MOCKER_(0, constness, Method).With();

Simply removing the & from all 15 specializations seems to fix the problems, but given that a large part of MOCK_GLOBAL_FUNC0_ is an exact duplicate of MOCK_METHOD0_, I subsequently changed to this:

#define MOCK_GLOBAL_FUNC0_(tn, constness, ct, Method, ...) \
class gmock_globalmock_##Method { \
public:\
  gmock_globalmock_##Method(const char* tag) : m_tag(tag) {}  \
  const char* const m_tag; \
  MOCK_METHOD0(Method, __VA_ARGS__); \
   }; \
   std::unique_ptr< gmock_globalmock_##Method > gmock_globalmock_##Method##_instance;\
   GMOCK_RESULT_(tn, __VA_ARGS__) ct Method() constness { \
         \
       return gmock_globalmock_##Method##_instance->Method();\
      }\

which reduces the amount of code to maintain, as well as gives some protection if GMock ever changes the internal implementation of MOCK_METHOD0.

The only issue is that gmock-global supports up to 15 arguments, while GMock only goes up to MOCK_METHOD10, so I can't do the same treatment for MOCK_GLOBAL_FUNC11 - 15.

Namespaces not working

How can I use calls with namespace? In my code I use different functions with namespaces (filesystem::exists etc.). But gmock-global not working correctly with namespaces.

I will show what I want with an examples.

I want to mock function:

namespace foo {
    int bar(std::string a) {
        return 2;
    }
}

Works

using foo::bar;

namespace {
    MOCK_GLOBAL_FUNC1(bar, int(std::string));

    TEST(config_parse_test, Success) {
        EXPECT_GLOBAL_CALL(bar, bar("baz")).WillOnce(Return(1));
        int a = bar("baz");

        ASSERT_EQ(a, 1);
    }
}

Other mock I need. Not works

namespace {
    MOCK_GLOBAL_FUNC1(bar, int(std::string));

    TEST(config_parse_test, Success) {
        EXPECT_GLOBAL_CALL(foo::bar, foo::bar("baz")).WillOnce(Return(1));
        int a = foo::bar("baz");

        ASSERT_EQ(a, 1);
    }
}

Error:

/some/path/to/unit/test.cpp: In member function ‘virtual void {anonymous}::config_parse_test_Success_Test::TestBody()’:
/some/path/to/tests/../gmock-global/include/gmock-global/gmock-global.h:910:45: error: ‘gmock_globalmock_foo’ was not declared in this scope
 #define GLOBAL_MOCK_TYPE(name)              gmock_globalmock_##name

Other variant mock I also need. Not works

using ::foo::bar;

namespace {
    MOCK_GLOBAL_FUNC1(bar, int(std::string));

    TEST(config_parse_test, Success) {
        EXPECT_GLOBAL_CALL(bar, bar("baz")).WillOnce(Return(1));
        int a = foo::bar("baz"); // Called in my code

        ASSERT_EQ(a, 1);
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.