Mocking a concrete class : templates and avoiding conditional compilation

Posted by AshirusNW on Stack Overflow See other posts from Stack Overflow or by AshirusNW
Published on 2010-04-16T16:47:13Z Indexed on 2010/05/12 13:04 UTC
Read the original article Hit count: 267

I'm trying to testing a concrete object with this sort of structure.

class Database {
 public:
  Database(Server server) : server_(server) {}
  int Query(const char* expression) {
    server_.Connect();
    return server_.ExecuteQuery();
  }

 private:
  Server server_;
};

i.e. it has no virtual functions, let alone a well-defined interface.

I want to a fake database which calls mock services for testing. Even worse, I want the same code to be either built against the real version or the fake so that the same testing code can both:

  • Test the real Database implementation - for integration tests
  • Test the fake implementation, which calls mock services

To solve this, I'm using a templated fake, like this:

#ifndef INTEGRATION_TESTS
class FakeDatabase {
 public:
  FakeDatabase() : realDb_(mockServer_) {}
  int Query(const char* expression) {
    MOCK_EXPECT_CALL(mockServer_, Query, 3);
    return realDb_.Query();
  }
private:
  // in non-INTEGRATION_TESTS builds, Server is a mock Server with
  // extra testing methods that allows mocking
  Server mockServer_;
  Database realDb_;
};
#endif

template <class T>
class TestDatabaseContainer {
 public:
  int Query(const char* expression) {
    int result = database_.Query(expression);
    std::cout << "LOG: " << result << endl;
    return result; 
  }
private:
  T database_;
};

Edit: Note the fake Database must call the real Database (but with a mock Server).

Now to switch between them I'm planning the following test framework:

class DatabaseTests {
 public:
#ifdef INTEGRATION_TESTS
  typedef TestDatabaseContainer<Database> TestDatabase ;
#else
  typedef TestDatabaseContainer<FakeDatabase> TestDatabase ;
#endif

  TestDatabase& GetDb() { return _testDatabase; }

 private: 
  TestDatabase _testDatabase;
};

class QueryTestCase : public DatabaseTests {
 public:
  void TestStep1() {
    ASSERT(GetDb().Query(static_cast<const char *>("")) == 3);
    return;
  }
};

I'm not a big fan of that compile-time switching between the real and the fake.

So, my question is:

  1. Whether there's a better way of switching between Database and FakeDatabase? For instance, is it possible to do it at runtime in a clean fashion? I like to avoid #ifdefs.
  2. Also, if anyone has a better way of making a fake class that mimics a concrete class, I'd appreciate it.

I don't want to have templated code all over the actual test code (QueryTestCase class).

Feel free to critique the code style itself, too. You can see a compiled version of this code on codepad.

© Stack Overflow or respective owner

Related posts about c++

Related posts about templates