Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>See below for FindFirstFile/FindNextFile/FindClose example</p> <hr> <p>I use <a href="https://github.com/google/googletest/blob/master/googlemock/README.md" rel="nofollow noreferrer">googlemock</a>. For an external API I generally create an interface class. Assume I was going to call fopen, fwrite, fclose</p> <pre><code>class FileIOInterface { public: ~virtual FileIOInterface() {} virtual FILE* Open(const char* filename, const char* mode) = 0; virtual size_t Write(const void* data, size_t size, size_t num, FILE* file) = 0; virtual int Close(FILE* file) = 0; }; </code></pre> <p>The actual implementation would be this</p> <pre><code>class FileIO : public FileIOInterface { public: virtual FILE* Open(const char* filename, const char* mode) { return fopen(filename, mode); } virtual size_t Write(const void* data, size_t size, size_t num, FILE* file) { return fwrite(data, size, num, file); } virtual int Close(FILE* file) { return fclose(file); } }; </code></pre> <p>Then using googlemock I make a MockFileIO class like this</p> <pre><code>class MockFileIO : public FileIOInterface { public: virtual ~MockFileIO() { } MOCK_MEHTOD2(Open, FILE*(const char* filename, const char* mode)); MOCK_METHOD4(Write, size_t(const void* data, size_t size, size_t num, FILE* file)); MOCK_METHOD1(Close, int(FILE* file)); } </code></pre> <p>This makes writing the tests easy. I don't have to provide a test implementation of Open/Write/Close. googlemock handles that for me. as in. (note I use <a href="http://code.google.com/p/googletest/" rel="nofollow noreferrer">googletest</a> for my unit testing framework.)</p> <p>Assume I have a function like this that needs testing</p> <pre><code>// Writes a file, returns true on success. bool WriteFile(FileIOInterface fio, const char* filename, const void* data, size_size) { FILE* file = fio.Open(filename, "wb"); if (!file) { return false; } if (fio.Write(data, 1, size, file) != size) { return false; } if (fio.Close(file) != 0) { return false; } return true; } </code></pre> <p>And here's the tests.</p> <pre><code>TEST(WriteFileTest, SuccessWorks) { MockFileIO fio; static char data[] = "hello"; const char* kName = "test"; File test_file; // Tell the mock to expect certain calls and what to // return on those calls. EXPECT_CALL(fio, Open(kName, "wb") .WillOnce(Return(&amp;test_file)); EXPECT_CALL(fio, Write(&amp;data, 1, sizeof(data), &amp;test_file)) .WillOnce(Return(sizeof(data))); EXPECT_CALL(file, Close(&amp;test_file)) .WillOnce(Return(0)); EXPECT_TRUE(WriteFile(kName, &amp;data, sizeof(data)); } TEST(WriteFileTest, FailsIfOpenFails) { MockFileIO fio; static char data[] = "hello"; const char* kName = "test"; File test_file; // Tell the mock to expect certain calls and what to // return on those calls. EXPECT_CALL(fio, Open(kName, "wb") .WillOnce(Return(NULL)); EXPECT_FALSE(WriteFile(kName, &amp;data, sizeof(data)); } TEST(WriteFileTest, FailsIfWriteFails) { MockFileIO fio; static char data[] = "hello"; const char* kName = "test"; File test_file; // Tell the mock to expect certain calls and what to // return on those calls. EXPECT_CALL(fio, Open(kName, "wb") .WillOnce(Return(&amp;test_file)); EXPECT_CALL(fio, Write(&amp;data, 1, sizeof(data), &amp;test_file)) .WillOnce(Return(0)); EXPECT_FALSE(WriteFile(kName, &amp;data, sizeof(data)); } TEST(WriteFileTest, FailsIfCloseFails) { MockFileIO fio; static char data[] = "hello"; const char* kName = "test"; File test_file; // Tell the mock to expect certain calls and what to // return on those calls. EXPECT_CALL(fio, Open(kName, "wb") .WillOnce(Return(&amp;test_file)); EXPECT_CALL(fio, Write(&amp;data, 1, sizeof(data), &amp;test_file)) .WillOnce(Return(sizeof(data))); EXPECT_CALL(file, Close(&amp;test_file)) .WillOnce(Return(EOF)); EXPECT_FALSE(WriteFile(kName, &amp;data, sizeof(data)); } </code></pre> <p>I didn't have to provide a test implementation of fopen/fwrite/fclose. googlemock handles this for me. You can make the mock strict if you want. A Strict mock will fail the tests if any function that is not expected is called or if any function that is expected is called with the wrong arguments. Googlemock provides a ton of helpers and adapters so you generally don't need to write much code to get the mock to do what you want. It takes a few days to learn the different adapters but if you're using it often they quickly become second nature.</p> <hr> <p>Here's an example using FindFirstFile, FindNextFile, FindClose</p> <p>First the interface</p> <pre><code>class FindFileInterface { public: virtual HANDLE FindFirstFile( LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData) = 0; virtual BOOL FindNextFile( HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData) = 0; virtual BOOL FindClose( HANDLE hFindFile) = 0; virtual DWORD GetLastError(void) = 0; }; </code></pre> <p>Then the actual implementation</p> <pre><code>class FindFileImpl : public FindFileInterface { public: virtual HANDLE FindFirstFile( LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData) { return ::FindFirstFile(lpFileName, lpFindFileData); } virtual BOOL FindNextFile( HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData) { return ::FindNextFile(hFindFile, lpFindFileData); } virtual BOOL FindClose( HANDLE hFindFile) { return ::FindClose(hFindFile); } virtual DWORD GetLastError(void) { return ::GetLastError(); } }; </code></pre> <p>The Mock using gmock</p> <pre><code>class MockFindFile : public FindFileInterface { public: MOCK_METHOD2(FindFirstFile, HANDLE(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData)); MOCK_METHOD2(FindNextFile, BOOL(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData)); MOCK_METHOD1(FindClose, BOOL(HANDLE hFindFile)); MOCK_METHOD0(GetLastError, DWORD()); }; </code></pre> <p>The function I need to test.</p> <pre><code>DWORD PrintListing(FindFileInterface* findFile, const TCHAR* path) { WIN32_FIND_DATA ffd; HANDLE hFind; hFind = findFile-&gt;FindFirstFile(path, &amp;ffd); if (hFind == INVALID_HANDLE_VALUE) { printf ("FindFirstFile failed"); return 0; } do { if (ffd.dwFileAttributes &amp; FILE_ATTRIBUTE_DIRECTORY) { _tprintf(TEXT(" %s &lt;DIR&gt;\n"), ffd.cFileName); } else { LARGE_INTEGER filesize; filesize.LowPart = ffd.nFileSizeLow; filesize.HighPart = ffd.nFileSizeHigh; _tprintf(TEXT(" %s %ld bytes\n"), ffd.cFileName, filesize.QuadPart); } } while(findFile-&gt;FindNextFile(hFind, &amp;ffd) != 0); DWORD dwError = findFile-&gt;GetLastError(); if (dwError != ERROR_NO_MORE_FILES) { _tprintf(TEXT("error %d"), dwError); } findFile-&gt;FindClose(hFind); return dwError; } </code></pre> <p>The unit tests.</p> <pre><code>#include &lt;gtest/gtest.h&gt; #include &lt;gmock/gmock.h&gt; using ::testing::_; using ::testing::Return; using ::testing::DoAll; using ::testing::SetArgumentPointee; // Some data for unit tests. static WIN32_FIND_DATA File1 = { FILE_ATTRIBUTE_NORMAL, // DWORD dwFileAttributes; { 123, 0, }, // FILETIME ftCreationTime; { 123, 0, }, // FILETIME ftLastAccessTime; { 123, 0, }, // FILETIME ftLastWriteTime; 0, // DWORD nFileSizeHigh; 123, // DWORD nFileSizeLow; 0, // DWORD dwReserved0; 0, // DWORD dwReserved1; { TEXT("foo.txt") }, // TCHAR cFileName[MAX_PATH]; { TEXT("foo.txt") }, // TCHAR cAlternateFileName[14]; }; static WIN32_FIND_DATA Dir1 = { FILE_ATTRIBUTE_DIRECTORY, // DWORD dwFileAttributes; { 123, 0, }, // FILETIME ftCreationTime; { 123, 0, }, // FILETIME ftLastAccessTime; { 123, 0, }, // FILETIME ftLastWriteTime; 0, // DWORD nFileSizeHigh; 123, // DWORD nFileSizeLow; 0, // DWORD dwReserved0; 0, // DWORD dwReserved1; { TEXT("foo.dir") }, // TCHAR cFileName[MAX_PATH]; { TEXT("foo.dir") }, // TCHAR cAlternateFileName[14]; }; TEST(PrintListingTest, TwoFiles) { const TCHAR* kPath = TEXT("c:\\*"); const HANDLE kValidHandle = reinterpret_cast&lt;HANDLE&gt;(1234); MockFindFile ff; EXPECT_CALL(ff, FindFirstFile(kPath, _)) .WillOnce(DoAll(SetArgumentPointee&lt;1&gt;(Dir1), Return(kValidHandle))); EXPECT_CALL(ff, FindNextFile(kValidHandle, _)) .WillOnce(DoAll(SetArgumentPointee&lt;1&gt;(File1), Return(TRUE))) .WillOnce(Return(FALSE)); EXPECT_CALL(ff, GetLastError()) .WillOnce(Return(ERROR_NO_MORE_FILES)); EXPECT_CALL(ff, FindClose(kValidHandle)); PrintListing(&amp;ff, kPath); } TEST(PrintListingTest, OneFile) { const TCHAR* kPath = TEXT("c:\\*"); const HANDLE kValidHandle = reinterpret_cast&lt;HANDLE&gt;(1234); MockFindFile ff; EXPECT_CALL(ff, FindFirstFile(kPath, _)) .WillOnce(DoAll(SetArgumentPointee&lt;1&gt;(Dir1), Return(kValidHandle))); EXPECT_CALL(ff, FindNextFile(kValidHandle, _)) .WillOnce(Return(FALSE)); EXPECT_CALL(ff, GetLastError()) .WillOnce(Return(ERROR_NO_MORE_FILES)); EXPECT_CALL(ff, FindClose(kValidHandle)); PrintListing(&amp;ff, kPath); } TEST(PrintListingTest, ZeroFiles) { const TCHAR* kPath = TEXT("c:\\*"); MockFindFile ff; EXPECT_CALL(ff, FindFirstFile(kPath, _)) .WillOnce(Return(INVALID_HANDLE_VALUE)); PrintListing(&amp;ff, kPath); } TEST(PrintListingTest, Error) { const TCHAR* kPath = TEXT("c:\\*"); const HANDLE kValidHandle = reinterpret_cast&lt;HANDLE&gt;(1234); MockFindFile ff; EXPECT_CALL(ff, FindFirstFile(kPath, _)) .WillOnce(DoAll(SetArgumentPointee&lt;1&gt;(Dir1), Return(kValidHandle))); EXPECT_CALL(ff, FindNextFile(kValidHandle, _)) .WillOnce(Return(FALSE)); EXPECT_CALL(ff, GetLastError()) .WillOnce(Return(ERROR_ACCESS_DENIED)); EXPECT_CALL(ff, FindClose(kValidHandle)); PrintListing(&amp;ff, kPath); } </code></pre> <p>I didn't have to implement any of the mock functions. </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload