Is this an idiomatic way to pass mocks into objects?
Posted
by Billy ONeal
on Stack Overflow
See other posts from Stack Overflow
or by Billy ONeal
Published on 2010-05-26T18:22:43Z
Indexed on
2010/05/26
18:51 UTC
Read the original article
Hit count: 326
I'm a bit confused about passing in this mock class into an implementation class. It feels wrong to have all this explicitly managed memory flying around. I'd just pass the class by value but that runs into the slicing problem.
Am I missing something here?
Implementation:
namespace detail
{
struct FileApi
{
virtual HANDLE CreateFileW(
__in LPCWSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_opt HANDLE hTemplateFile
)
{
return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
virtual void CloseHandle(HANDLE handleToClose)
{
::CloseHandle(handleToClose);
}
};
}
class File : boost::noncopyable
{
HANDLE hWin32;
boost::scoped_ptr<detail::FileApi> fileApi;
public:
File(
__in LPCWSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_opt HANDLE hTemplateFile,
__in detail::FileApi * method = new detail::FileApi()
)
{
fileApi.reset(method);
hWin32 = fileApi->CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
}; namespace detail
{
struct FileApi
{
virtual HANDLE CreateFileW(
__in LPCWSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_opt HANDLE hTemplateFile
)
{
return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
virtual void CloseHandle(HANDLE handleToClose)
{
::CloseHandle(handleToClose);
}
};
}
class File : boost::noncopyable
{
HANDLE hWin32;
boost::scoped_ptr<detail::FileApi> fileApi;
public:
File(
__in LPCWSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_opt HANDLE hTemplateFile,
__in detail::FileApi * method = new detail::FileApi()
)
{
fileApi.reset(method);
hWin32 = fileApi->CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
~File()
{
fileApi->CloseHandle(hWin32);
}
};
Tests:
namespace detail {
struct MockFileApi : public FileApi
{
MOCK_METHOD7(CreateFileW, HANDLE(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE));
MOCK_METHOD1(CloseHandle, void(HANDLE));
};
}
using namespace detail;
using namespace testing;
TEST(Test_File, OpenPassesArguments)
{
MockFileApi * api = new MockFileApi;
EXPECT_CALL(*api, CreateFileW(Eq(L"BozoFile"), Eq(56), Eq(72), Eq(reinterpret_cast<LPSECURITY_ATTRIBUTES>(67)), Eq(98), Eq(102), Eq(reinterpret_cast<HANDLE>(98))))
.Times(1).WillOnce(Return(reinterpret_cast<HANDLE>(42)));
File test(L"BozoFile", 56, 72, reinterpret_cast<LPSECURITY_ATTRIBUTES>(67), 98, 102, reinterpret_cast<HANDLE>(98), api);
}
© Stack Overflow or respective owner