title: Mocking with Boost::Test
body: <p>I'm using the Boost::Test library for unit testing, and I've in general been hacking up my own mocking solutions that look something like this:</p>
  
  <pre><code>//In header for clients
  struct RealFindFirstFile
  {
      static HANDLE FindFirst(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData) {
          return FindFirstFile(lpFileName, lpFindFileData);
      };
  };
  
  template &lt;typename FirstFile_T = RealFindFirstFile&gt;
  class DirectoryIterator {
  //.. Implementation
  }
  
  //In unit tests (cpp)
  #define THE_ANSWER_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING 42
  struct FakeFindFirstFile
  {
      static HANDLE FindFirst(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData) {
          return THE_ANSWER_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING;
      };
  };
  BOOST_AUTO_TEST_CASE( MyTest )
  {
      DirectoryIterator&lt;FakeFindFirstFile&gt; LookMaImMocked;
      //Test
  }
  </code></pre>
  
  <p>I've grown frustrated with this because it requires that I implement almost everything as a template, and it is a lot of boilerplate code to achieve what I'm looking for.</p>
  
  <p>Is there a good method of mocking up code using Boost::Test over my Ad-hoc method?</p>
  
  <p>I've seen several people recommend Google Mock, but it requires a lot of ugly hacks if your functions are not <code>virtual</code>, which I would like to avoid.</p>
  
  <p>Oh: One last thing. I don't need assertions that a particular piece of code was called. I simply need to be able to inject data that would normally be returned by Windows API functions.</p>
  
  <p>EDIT: Here is an example class set and the tests I have for it:</p>
  
  <p>The classes under test:</p>
  
  <pre><code>#include &lt;list&gt;
  #include &lt;string&gt;
  #include &lt;boost/noncopyable.hpp&gt;
  #include &lt;boost/make_shared.hpp&gt;
  #include &lt;boost/iterator/iterator_facade.hpp&gt;
  #include &lt;Windows.h&gt;
  #include &lt;Shlwapi.h&gt;
  #pragma comment(lib, "shlwapi.lib")
  #include "../Exception.hpp"
  
  namespace WindowsAPI { namespace FileSystem {
  
  //For unit testing
  struct RealFindXFileFunctions
  {
      HANDLE FindFirst(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData) {
          return FindFirstFile(lpFileName, lpFindFileData);
      };
      BOOL FindNext(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData) {
          return FindNextFile(hFindFile, lpFindFileData);
      };
      BOOL Close(HANDLE hFindFile) {
          return FindClose(hFindFile);
      };
  };
  
  class Win32FindData {
      WIN32_FIND_DATA internalData;
      std::wstring rootPath;
  public:
      Win32FindData(const std::wstring&amp; root, const WIN32_FIND_DATA&amp; data) :
          rootPath(root), internalData(data) {};
      DWORD GetAttributes() const {
          return internalData.dwFileAttributes;
      };
      bool IsDirectory() const {
          return (internalData.dwFileAttributes &amp; FILE_ATTRIBUTE_DIRECTORY) != 0;
      };
      bool IsFile() const {
          return !IsDirectory();
      };
      unsigned __int64 GetSize() const {
          ULARGE_INTEGER intValue;
          intValue.LowPart = internalData.nFileSizeLow;
          intValue.HighPart = internalData.nFileSizeHigh;
          return intValue.QuadPart;
      };
      std::wstring GetFolderPath() const {
          return rootPath;
      };
      std::wstring GetFileName() const {
          return internalData.cFileName;
      };
      std::wstring GetFullFileName() const {
          return rootPath + L"\\" + internalData.cFileName;
      };
      std::wstring GetShortFileName() const {
          return internalData.cAlternateFileName;
      };
      FILETIME GetCreationTime() const {
          return internalData.ftCreationTime;
      };
      FILETIME GetLastAccessTime() const {
          return internalData.ftLastAccessTime;
      };
      FILETIME GetLastWriteTime() const {
          return internalData.ftLastWriteTime;
      };
  };
  
  template &lt;typename FindXFileFunctions_T&gt;
  class BasicEnumerationMethod : public boost::noncopyable {
  protected:
      WIN32_FIND_DATAW currentData;
      HANDLE hFind;
      std::wstring currentDirectory;
      FindXFileFunctions_T FindFileFunctions;
      BasicEnumerationMethod(FindXFileFunctions_T functor) :
          hFind(INVALID_HANDLE_VALUE),
          FindFileFunctions(functor) {};
      void IncrementCurrentDirectory() {
          if (hFind == INVALID_HANDLE_VALUE) return;
          BOOL success =
              FindFileFunctions.FindNext(hFind, &amp;currentData);
          if (success)
              return;
          DWORD error = GetLastError();
          if (error == ERROR_NO_MORE_FILES) {
              FindFileFunctions.Close(hFind);
              hFind = INVALID_HANDLE_VALUE;
          } else {
              WindowsApiException::Throw(error);
          }
      };
      virtual ~BasicEnumerationMethod() {
          if (hFind != INVALID_HANDLE_VALUE)
              FindFileFunctions.Close(hFind);
      };
  public:
      bool equal(const BasicEnumerationMethod&lt;FindXFileFunctions_T&gt;&amp; other) const {
          if (this == &amp;other)
              return true;
          return hFind == other.hFind;
      };
      Win32FindData dereference() {
          return Win32FindData(currentDirectory, currentData);
      };
  };
  
  template &lt;typename FindXFileFunctions_T&gt;
  class BasicNonRecursiveEnumeration : public BasicEnumerationMethod&lt;FindXFileFunctions_T&gt;
  {
  public:
      BasicNonRecursiveEnumeration(FindXFileFunctions_T functor = FindXFileFunctions_T())
          : BasicEnumerationMethod&lt;FindXFileFunctions_T&gt;(functor) {};
      BasicNonRecursiveEnumeration(const std::wstring&amp; pathSpec,
              FindXFileFunctions_T functor = FindXFileFunctions_T())
              : BasicEnumerationMethod&lt;FindXFileFunctions_T&gt;(functor) {
          std::wstring::const_iterator lastSlash =
              std::find(pathSpec.rbegin(), pathSpec.rend(), L'\\').base();
          if (lastSlash != pathSpec.begin())
              currentDirectory.assign(pathSpec.begin(), lastSlash-1);
          hFind = FindFileFunctions.FindFirst(pathSpec.c_str(), &amp;currentData);
          if (hFind == INVALID_HANDLE_VALUE
              &amp;&amp; GetLastError() != ERROR_PATH_NOT_FOUND
              &amp;&amp; GetLastError() != ERROR_FILE_NOT_FOUND)
              WindowsApiException::ThrowFromLastError();
          while (hFind != INVALID_HANDLE_VALUE &amp;&amp; (!wcscmp(currentData.cFileName, L".") ||
                  !wcscmp(currentData.cFileName, L".."))) {
              IncrementCurrentDirectory();
          }
      };
      void increment() {
          IncrementCurrentDirectory();
      };
  };
  
  typedef BasicNonRecursiveEnumeration&lt;RealFindXFileFunctions&gt; NonRecursiveEnumeration;
  
  template &lt;typename FindXFileFunctions_T&gt;
  class BasicRecursiveEnumeration : public BasicEnumerationMethod&lt;FindXFileFunctions_T&gt;
  {
      //Implementation ommitted
  };
  
  typedef BasicRecursiveEnumeration&lt;RealFindXFileFunctions&gt; RecursiveEnumeration;
  
  struct AllResults
  {
      bool operator()(const Win32FindData&amp;) {
          return true;
      };
  }; 
  
  struct FilesOnly
  {
      bool operator()(const Win32FindData&amp; arg) {
          return arg.IsFile();
      };
  };
  
  template &lt;typename Filter_T = AllResults, typename Recurse_T = NonRecursiveEnumeration&gt;
  class DirectoryIterator : 
      public boost::iterator_facade&lt;
          DirectoryIterator&lt;Filter_T, Recurse_T&gt;,
          Win32FindData,
          std::input_iterator_tag,
          Win32FindData
      &gt;
  {
      friend class boost::iterator_core_access;
      boost::shared_ptr&lt;Recurse_T&gt; impl;
      Filter_T filter;
      void increment() {
          do {
              impl-&gt;increment();
          } while (! filter(impl-&gt;dereference()));
      };
      bool equal(const DirectoryIterator&amp; other) const {
          return impl-&gt;equal(*other.impl);
      };
      Win32FindData dereference() const {
          return impl-&gt;dereference();
      };
  public:
      DirectoryIterator(Filter_T functor = Filter_T()) :
          impl(boost::make_shared&lt;Recurse_T&gt;()),
          filter(functor) {
      };
      explicit DirectoryIterator(const std::wstring&amp; pathSpec, Filter_T functor = Filter_T()) :
          impl(boost::make_shared&lt;Recurse_T&gt;(pathSpec)),
          filter(functor) {
      };
  };
  
  }}
  </code></pre>
  
  <p>Tests for this class:</p>
  
  <pre><code>#include &lt;queue&gt;
  #include "../WideCharacterOutput.hpp"
  #include &lt;boost/test/unit_test.hpp&gt;
  #include "../../WindowsAPI++/FileSystem/Enumerator.hpp"
  using namespace WindowsAPI::FileSystem;
  
  struct SimpleFakeFindXFileFunctions
  {
      static std::deque&lt;WIN32_FIND_DATAW&gt; fakeData;
      static std::wstring insertedFileName;
  
      HANDLE FindFirst(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData) {
          insertedFileName.assign(lpFileName);
          if (fakeData.empty()) {
              SetLastError(ERROR_PATH_NOT_FOUND);
              return INVALID_HANDLE_VALUE;
          }
          *lpFindFileData = fakeData.front();
          fakeData.pop_front();
          return reinterpret_cast&lt;HANDLE&gt;(42);
      };
      BOOL FindNext(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData) {
          BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile);
          if (fakeData.empty()) {
              SetLastError(ERROR_NO_MORE_FILES);
              return 0;
          }
          *lpFindFileData = fakeData.front();
          fakeData.pop_front();
          return 1;
      };
      BOOL Close(HANDLE hFindFile) {
          BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile);
          return 1;
      };
  };
  
  std::deque&lt;WIN32_FIND_DATAW&gt; SimpleFakeFindXFileFunctions::fakeData;
  std::wstring SimpleFakeFindXFileFunctions::insertedFileName;
  
  struct ErroneousFindXFileFunctions
  {
      virtual HANDLE FindFirst(LPCWSTR, LPWIN32_FIND_DATAW) {
          return reinterpret_cast&lt;HANDLE&gt;(42);
      };
      virtual BOOL FindNext(HANDLE hFindFile, LPWIN32_FIND_DATAW) {
          BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile);
          return 1;
      };
      virtual BOOL Close(HANDLE hFindFile) {
          BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile);
          return 1;
      };
  };
  
  struct ErroneousFindXFileFunctionFirst : public ErroneousFindXFileFunctions
  {
      HANDLE FindFirst(LPCWSTR, LPWIN32_FIND_DATAW) {
          SetLastError(ERROR_ACCESS_DENIED);
          return INVALID_HANDLE_VALUE;
      };
  };
  
  struct ErroneousFindXFileFunctionNext : public ErroneousFindXFileFunctions
  {
      BOOL FindNext(HANDLE hFindFile, LPWIN32_FIND_DATAW) {
          BOOST_CHECK_EQUAL(reinterpret_cast&lt;HANDLE&gt;(42), hFindFile);
          SetLastError(ERROR_INVALID_PARAMETER);
          return 0;
      };
  };
  
  struct DirectoryIteratorTestsFixture
  {
      typedef SimpleFakeFindXFileFunctions fakeFunctor;
      DirectoryIteratorTestsFixture() {
          WIN32_FIND_DATAW test;
          wcscpy_s(test.cFileName, L".");
          wcscpy_s(test.cAlternateFileName, L".");
          test.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
          GetSystemTimeAsFileTime(&amp;test.ftCreationTime);
          test.ftLastWriteTime = test.ftCreationTime;
          test.ftLastAccessTime = test.ftCreationTime;
          test.nFileSizeHigh = 0;
          test.nFileSizeLow = 0;
          fakeFunctor::fakeData.push_back(test);
  
          wcscpy_s(test.cFileName, L"..");
          wcscpy_s(test.cAlternateFileName, L"..");
          fakeFunctor::fakeData.push_back(test);
  
          wcscpy_s(test.cFileName, L"File.txt");
          wcscpy_s(test.cAlternateFileName, L"FILE.TXT");
          test.nFileSizeLow = 1024;
          test.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
          fakeFunctor::fakeData.push_back(test);
  
          wcscpy_s(test.cFileName, L"System32");
          wcscpy_s(test.cAlternateFileName, L"SYSTEM32");
          test.nFileSizeLow = 0;
          test.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
          fakeFunctor::fakeData.push_back(test);
      };
      ~DirectoryIteratorTestsFixture() {
          fakeFunctor::fakeData.clear();
      };
  };
  
  BOOST_FIXTURE_TEST_SUITE( DirectoryIteratorTests, DirectoryIteratorTestsFixture )
  
  BOOST_AUTO_TEST_CASE( BasicEnumeration )
  {
      typedef DirectoryIterator&lt;AllResults
          ,BasicNonRecursiveEnumeration&lt;SimpleFakeFindXFileFunctions&gt; &gt; testType;
      testType begin(L"C:\\Windows\\*");
      testType end;
      BOOST_CHECK_EQUAL(fakeFunctor::insertedFileName, L"C:\\Windows\\*");
      BOOST_CHECK(begin-&gt;GetFolderPath() == L"C:\\Windows");
      BOOST_CHECK(begin-&gt;GetFileName() == L"File.txt");
      BOOST_CHECK(begin-&gt;GetFullFileName() == L"C:\\Windows\\File.txt");
      BOOST_CHECK(begin-&gt;GetShortFileName() == L"FILE.TXT");
      BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 1024);
      BOOST_CHECK(begin-&gt;IsFile());
      BOOST_CHECK(begin != end);
      begin++;
      BOOST_CHECK(begin-&gt;GetFileName() == L"System32");
      BOOST_CHECK(begin-&gt;GetFullFileName() == L"C:\\Windows\\System32");
      BOOST_CHECK(begin-&gt;GetShortFileName() == L"SYSTEM32");
      BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 0);
      BOOST_CHECK(begin-&gt;IsDirectory());
      begin++;
      BOOST_CHECK(begin == end);
  }
  
  BOOST_AUTO_TEST_CASE( NoRootDirectories )
  {
      typedef DirectoryIterator&lt;AllResults
          ,BasicNonRecursiveEnumeration&lt;SimpleFakeFindXFileFunctions&gt; &gt; testType;
      fakeFunctor::fakeData.pop_front();
      fakeFunctor::fakeData.pop_front();
      testType begin(L"C:\\Windows\\*");
      testType end;
      BOOST_CHECK_EQUAL(fakeFunctor::insertedFileName, L"C:\\Windows\\*");
      BOOST_CHECK(begin-&gt;GetFolderPath() == L"C:\\Windows");
      BOOST_CHECK(begin-&gt;GetFileName() == L"File.txt");
      BOOST_CHECK(begin-&gt;GetFullFileName() == L"C:\\Windows\\File.txt");
      BOOST_CHECK(begin-&gt;GetShortFileName() == L"FILE.TXT");
      BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 1024);
      BOOST_CHECK(begin-&gt;IsFile());
      BOOST_CHECK(begin != end);
      begin++;
      BOOST_CHECK(begin-&gt;GetFileName() == L"System32");
      BOOST_CHECK(begin-&gt;GetFullFileName() == L"C:\\Windows\\System32");
      BOOST_CHECK(begin-&gt;GetShortFileName() == L"SYSTEM32");
      BOOST_CHECK_EQUAL(begin-&gt;GetSize(), 0);
      BOOST_CHECK(begin-&gt;IsDirectory());
      begin++;
      BOOST_CHECK(begin == end);
  }
  
  BOOST_AUTO_TEST_CASE( Empty1 )
  {
      fakeFunctor::fakeData.clear();
      typedef DirectoryIterator&lt;AllResults
          ,BasicNonRecursiveEnumeration&lt;SimpleFakeFindXFileFunctions&gt; &gt; testType;
      testType begin(L"C:\\Windows\\*");
      testType end;
      BOOST_CHECK(begin == end);
  }
  
  BOOST_AUTO_TEST_CASE( Empty2 )
  {
      fakeFunctor::fakeData.erase(fakeFunctor::fakeData.begin() + 2, fakeFunctor::fakeData.end());
      typedef DirectoryIterator&lt;AllResults
          ,BasicNonRecursiveEnumeration&lt;SimpleFakeFindXFileFunctions&gt; &gt; testType;
      testType begin(L"C:\\Windows\\*");
      testType end;
      BOOST_CHECK(begin == end);
  }
  
  BOOST_AUTO_TEST_CASE( Exceptions )
  {
      typedef DirectoryIterator&lt;AllResults,BasicNonRecursiveEnumeration&lt;ErroneousFindXFileFunctionFirst&gt; &gt;
          firstFailType;
      BOOST_CHECK_THROW(firstFailType(L"C:\\Windows\\*"), WindowsAPI::ErrorAccessDeniedException);
      typedef DirectoryIterator&lt;AllResults,BasicNonRecursiveEnumeration&lt;ErroneousFindXFileFunctionNext&gt; &gt;
          nextFailType;
      nextFailType constructedOkay(L"C:\\Windows\\*");
      BOOST_CHECK_THROW(constructedOkay++, WindowsAPI::ErrorInvalidParameterException);
  }
  
  BOOST_AUTO_TEST_CASE( CorrectDestruction )
  {
      typedef DirectoryIterator&lt;AllResults
          ,BasicNonRecursiveEnumeration&lt;SimpleFakeFindXFileFunctions&gt; &gt; testType;
      testType begin(L"C:\\Windows\\*");
      testType end;
      BOOST_CHECK(begin != end);
  }
  
  BOOST_AUTO_TEST_SUITE_END()
  </code></pre>