eranpeer / FakeIt

C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.
MIT License
1.23k stars 169 forks source link

Mocking a `static` method? #181

Open jaques-sam opened 4 years ago

jaques-sam commented 4 years ago
class TestClass
{
public:
    static void create() {};
};

Mock<TestClass> testClass;
When(Method(testClass, create));

Build error: 'template' keyword not permitted here

hedayat commented 4 years ago

AFAIK, mocking non-virtual methods are not supported by FakeIt.

oriolarcas commented 4 years ago

My workaround is creating another class with a method for each static method, and mock it:

class TestClass
{
public:
    static void create(); // declaration of the static method
};

class TestClassStaticMethods
{
public:
    virtual void create() = 0;
};

Mock<TestClassStaticMethods> testClassStaticMethods;

/* Definition of the static method */
void TestClass::create() {
    testClassStaticMethods.get().create();
}

When(Method(testClassStaticMethods, create));
jaques-sam commented 4 years ago

Thanks @oriolarcas, this seems like a good approach! This is something what FakeIt could do to make this work.

dolfandringa commented 4 years ago

For others coming along this question, I have a similar use case and found a workaround too. With TestClass being the class that is tested, which calls an external class, which I am mocking with MockExternalClass, which has a static method, and want to verify that a function on it was called.

I basically added a pointer to the class as a static member variable, and return the value of it by reference from the static getInstance method.

#include "fakeit.hpp"
using namespace fakeit;

class MockExternalClass {
    public:
        int i = 1;
        static MockExternalClass *_mc;
        static MockExternalClass& getInstance() {
            return *MockExternalClass::_mc;
        }
        virtual void doSomething(){
            i++;
        };
};
MockExternalClass *MockExternalClass::_mc;

class TestClass {
    public:
        void myFunc() {
            MockExternalClass &test = MockExternalClass::getInstance();
            test.doSomething();
        }
};

int main() {

    Mock<MockExternalClass> mockTest;
    When(Method(mockTest, doSomething)).AlwaysReturn();
    MockExternalClass &mc = mockTest.get();
    MockExternalClass::_mc = &mc;
    TestClass t;
    t.myFunc();
    Verify(Method(mockTest, doSomething)).Once();
}
hedayat commented 4 years ago

Well, I wonder if it is appropriate, but you might also check my PowerFake for mocking a number of non-virtual functions: https://github.com/hedayat/powerfake

It also provides FakeIt integration through its PowerFakeIt.

Not much doc yet, but you can check the sample directory for a number of examples used with and without FakeIt integration.

Note: it has some limitations and currently provides easy CMake integration. For other build systems it'll need some work.