rollbear / trompeloeil

Header only C++14 mocking framework
Boost Software License 1.0
802 stars 85 forks source link

how can I mock the static member function and non-virtual member fuctions? #312

Open garinyang opened 11 months ago

garinyang commented 11 months ago

I've compared this proj with gmock ,and try to practice in my project, but I don't know how to mock the static and non-virtual member functions, who know?

//////////////////////////////////// class Test { public: Test(A* aa): a(aa) {

}

// 待测试函数
int Func(int i, int j) {

    auto x = i << 1;
    auto y = j << 1;
    std::cout << x << "," << y << std::endl;
    auto res = a->Add(x, y);

    return res;

}

private: A *a {nullptr}; };

class MockA : public A { public: MAKE_MOCK2(Add, int(int,int)); }; //////////////////////////////////// TEST_CASE("Demo Test") {

SUBCASE("hhh") {
    auto ma = new MockA();
    auto t = new Test(ma);

    using trompeloeil::_;

    // mock here
    REQUIRE_CALL(*ma, Add(4,6)).RETURN(999);

    auto res = t->Func(2, 3);

    CHECK(res==999);
}

} ////////////////////////////////////

I used MockA with dependcy injection , when I call Func(), the mock funciton Add() will be called, but still got the following Error , I don't konw why ???

Unfulfilled expectation: Expected *ma.Add(4,6) to be called once, actually never called param _1 == 4 param _2 == 6

xxx:172: FATAL ERROR: test case CRASHED: SIGABRT - Abort (abnormal termination) signal

rollbear commented 11 months ago

You have not shown what A looks like above, so it's not obvious what's happening, but it looks to me like you're expecting the library to work outside the rules of the language.

Unless A has a virtual function Add(int, int), then the call a->Add(x,y) is going to call the function in A::Add, no your MockA.::Add.

To answer the questions you asked: Static member functions cannot be mocked. Non-virtual functions can be mocked, but its use is limited. If it's not virtual, then obviously virtual dispatch won't happen. But it can be useful if the type is deduced in a template.

(contrived example)

template <typename T>
void test_func_call(T& t)
{
    assert(t.func(1) > 0);
}

struct mock
{
    MAKE_MOCK1(func, int(int));
};

int main()
{
    mock m;
    REQUIRE_CALL(m, func(1)).RETURN(3);

    test_func(m);
}
garinyang commented 11 months ago

yes, the function Add is virtual funciton as following: class A { public: virtual int Add(int a, int b) { return a + b; } };

about the point "Non-virtual functions can be mocked, but its use is limited."
RE: in case that I want to test the logic impl of a member functionA , and functionA called functionB which provided by another class, so I want to mock functionB, so that I can test only the logic impl of funcA. ^_^ If I used in my old project, it's not a good way to modify those 'old code', also it's not permitted, I think.