I have searched on this and did not find much information.
I have a below pattern of code where I have 1 class dedicated to load and unload dll in constructor and destructor respectively. Also the class has member variables which will hold the address to the functions to the dll.
Now this DllLoader
is used by some other class. I want to mock the DllLoader
so that the test I write for other class is specific to that function.
Example:
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;
};
I have tried the below, but I get exception while calling the fun1() inside init(). What am I doing wrong here?
I have not tested the code given as example here. But the flow is same.
//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
});
}
class SomeFunctionality
{
public:
virtual ~SomeFunctionality();
virtual int function1(int) = 0;
};
//cpp
SomeFunctionality::~SomeFunctionality() = default;
class SomeFunctionalityFromDll : public SomeFunctionality
{
public:
explicit SomeFunctionalityFromDll(const std::string& dll_name)
{
handle = ::LoadLibrary(dll_name);
fun1 = (fun_ptr1)GetProcAddress(handle, "DLLFunction1");
}
~SomeFunctionalityFromDll()
{
FreeLibrary(handle);
}
SomeFunctionalityFromDll(const SomeFunctionalityFromDll&) = delete;
SomeFunctionalityFromDll& operator=(const SomeFunctionalityFromDll&) = delete;
int function1(int x) override
{
return fun1(x);
}
private:
fun_ptr1 fun1;
HANDLE handle;
};
class SomeClass {
public:
explicit SomeClass(SomeFunctionality* dependency) : dependency(dependency)
{}
void init() {
int res = dependency->function1(100);
if(res < 50) {
//
} else {
//
}
}
SomeFunctionality* dependency;
};
class MockSomeFunctionality : public SomeFunctionality
{
public:
MOCK_METHOD(int, function1, (int), (override));
};
TEST(SomeClassTest, initWillInvokeFunction1)
{
MockSomeFunctionality mock;
EXPECT_CALL(mock, function1(100)).WillOnce(::testing::Return(12));
SomeClass prodClass{&mock};
prodClass.init();
}
https://godbolt.org/z/KbevWWcnn
The disadvantage is that you have extra indirection to call "DLLFunction1". If this is a problem it can be removed by static polymorphism (using templates).