如何将 gmock 函数赋值给特定函数指针?

3
我正在使用Gtest和Gmock进行C++的单元测试,针对两个dll:A.dll和B.dll。它们都是用C语言编写的,我不能对它们进行修改。
A.dll的`init`函数通过函数指针使用B.dll的函数作为参数。我希望模拟B的函数(因为它们是硬件相关的)。
我为A.dll创建了一个测试装置类,该类动态加载`init`和`calc`函数。以下代码简要介绍了感兴趣的函数内容:
class TestFixture : public ::testing::Test {
    // dynamically loads functions from A.dll and assigns
    // them to function pointers init_ptr and calc_ptr.
};

// function pointer typedef for use with B.dll's functions
typedef int (*funcPtr)(int, int);

// Loaded from A.dll    
void init(funcPtr func1, funcPtr func2) {
    // internally set functions in A.dll to be used in calculate
}

// Loaded from A.dll
int calculate(int a, int b) {
    // returns a+b + a+b
    return func1(func2(a,b), func2(a,b));
}

// Inside B.dll, should be mocked
int add(int a, int b) { return a+b; }

// Dummy class for B.dll
class B {
    virtual ~B() {}
    virtual int add(int a, int b) = 0;    
};

class MockB : public B {
virtual ~MockB() {}
    MOCK_METHOD(int, add, (int a, int b));
};

// Following example test run is the goal:
TEST_F(TestFixture, AddTest) {
    MockB b;

    // want to use mocked add function here
    init_ptr(mockedAdd, mockedAdd);

    EXPECT_CALL(b, add(_,_)).Times(3);
    EXPECT_EQ(calc_ptr(2,3), 10);
}

当我尝试创建一个虚拟类B和一个MockB类时,我无法将模拟方法分配给函数指针,这是init_ptr(funcPtr, funcPtr)所需的。是否有一种使用Gmock(或类似框架)实现这一点的方法?


看起来你在问题上搞砸了什么。单元测试应该测试你的代码而不是外部代码(dll),所以你正在测试的东西看起来很奇怪。我希望你有一些使用dll功能的代码,并且为了测试目的,你正在使用由该dll提供的功能模拟。因此,在dll被使用时难以重现场景的情况下,可以针对你的代码进行测试。请提供更多上下文,因为看起来你做错了什么或者误解了mock的用途。 - Marek R
目标是提供一个框架来测试依赖于硬件的dllB的dllA。 - Daniel
不,我没有访问源代码的权限。我只提供一个测试框架,最好包括模拟功能。 - Daniel
在正常情况下,您需要为您的代码编写测试,并模拟所有不属于您的内容,例如外部dll库等。这样做的好处是,模拟可以模拟依赖项(dll或其他库)可能出现的异常情况。 - Marek R
这确实很不寻常,我完全同意 :) - Daniel
显示剩余2条评论
1个回答

5
最简单的解决方法是声明一个静态(或自由)函数来调用模拟对象。
class Fixture : public ::testing::Test
{
public:
    static int add(int a, int b)
    {
        return mock_.add(a, b);
    }

    static MockB mock_;
};

MockB Fixture::mock_; // static declaration somewhere in .cpp

TEST_F(Fixture, MyTest)
{
    EXPECT_CALL(mock_, add(_, _));
    init(Fixture::add, Fixture::add);
}

我尝试了你的方法,但在链接时出现了 undefined reference to `Fixture::mock_` 的错误。不确定原因,但我会继续努力尝试。 - Daniel
@Daniel,这个模拟对象是静态的。静态成员必须在源文件中声明。我已经更新了答案。 - local-ninja
谢谢fdan,我应该现在就知道那个错误信息了。它现在像你建议的那样工作!您有任何建议如何将此过程应用于各种函数的长列表吗? - Daniel
这个答案现在对我来说更有意义了。虽然我也在选择使用Gmock和FFF来模拟C函数方面感到犹豫。 - Daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接