如何使用Gmock模拟dll函数?

问题描述 投票:0回答:1

我对此进行了搜索,但没有找到太多信息。可能我需要更多搜索,但我仍然会继续在这里提出问题。

我有一个下面的代码模式,其中有 1 个类专门用于分别在构造函数和析构函数中加载和卸载 dll。该类还具有成员变量,用于保存 dll 函数的地址。

现在这个

DllLoader
被其他一些类使用。我想模拟
DllLoader
,以便我为其他类编写的测试特定于该函数。

示例:

typedef int(*fun_ptr)(int);

class DllLoader {
public:
DllLoader(const std::string& dll_name) : handle(nullptr), fun1(nullptr) {

handle = ::LoadLibrary(dll_name);
fun1 = (fun_ptr1)GetProcAddress(handle, "DLLFunction1");
}

fun_ptr1 fun1;
HANDLE handle;
};

class SomeClass {
public:
SomeClass(DllLoader* dll_loader) : dll(dll_loader) {}

void init() {

int res = dll->fun1(100); // I want to use mock for fun1() call. Exception!!!
if(res < 50) {
//
}
else {
//
}
}

DllLoader* dll;
};

我尝试了以下方法,但在 init() 内调用 fun1() 时出现异常。不知道我在这里做错了什么。有人可以帮我吗?

我尚未测试此处作为示例给出的代码。但流程是一样的。

//created a mock class for DllLoader
class MockDllLoader : public DllLoader {
public:
MockDllLoader() : DllLoader("");
MOCK_METHOD(int, fun1, (int));
}; 


TEST(SomeClassTest, TestInit) {
MockDllLoader *mock_dll_loader = new MocDllLoader();
SomeClass * some_class = new SomeClass(mock_dll_loader);
EXPECT_CALL(*mock_dll_loader, fun1(::testing::_)).WillOnce(Return(1000));

EXPECT_NO_THROW({
some_class->init(); //expecting init to use the mocked function
});
}
c++17 googletest googlemock
1个回答
0
投票

使代码易于测试很难。

但是,在您的示例代码中(如果

fun1
是公共的)它可以像设置成员变量一样简单。

这是一个低成本的解决方案,通过将值设置为虚拟函数。当然,如果你需要mock能力,你可以使用

return_self
函数来创建一个mock对象并设置一些期望。

typedef int(*fun_ptr)(int);

class DllLoader {
public:
    DllLoader() {
        handle = ::LoadLibrary(dll_name);
        fun1 = (fun_ptr1)GetProcAddress(handle, "DLLFunction1");
    }

    fun_ptr fun1;
    HANDLE handle;
};

int return_self(int i) {
    return i;
};

int main(void)
{
    DllLoader d;
    d.fun1 = &return_self;
    
    std::cout << d.fun1(10);
    return 0;
}

如果它不是公开的(但您可以更改

DllLoader
类),我会在
DllLoader
之上创建一个接口,并在单元测试中使用模拟接口,并在实际应用。
类似这样的:

DllLoader

然后就像将模拟的 
class IDllLoader { public: void callFunction() = 0; }; class DllLoader : public IDllLoader { ... };

传递给您的

IDllLoader
一样简单,然后您就可以设置测试了。
通过使用该接口,您还可以避免调用真正的 

SomeClass

的构造函数,因此跳过

DllLoader
::LoadLibrary
调用(我认为在单元测试期间会很好)。
    

© www.soinside.com 2019 - 2024. All rights reserved.