[odb-users] Unit Testing, Mocking of classes that contain ODB code

Boris Kolpackov boris at codesynthesis.com
Sun Oct 19 10:48:16 EDT 2014


Hi Iris,

Iris-Marie Köster <imk at qosmotec.com> writes:

> void OdbInstance::load(DatabaseEntity * pEntity)
> {
>        m_database->load(pEntity->getId(), *pEntity);
> }

What you are trying to do is load an object via its base interface.
This will only work if you enable polymorphism support for your class
hierarchy that starts with DatabaseEntity. Section 8.2, "Polymorphism
Inheritance" describes this in detail and it is a good idea to read
it first before deciding to use this mechanism since the database
mapping will be very different. Enabling it just to support unit
testing might be an overkill.


> When I try to compile this, I get funny error messages:
>
> 'find' is not an element of  'odb::object_traits_impl<T,id_common>'

My guess is DatabaseEntity is abstract and non-polymorphic (in ODB
sense) thus the error.


> 2) Does anyone have experience with Unit Testing classes that 
>    use odb-code? Did you mock the database access or not?

I haven't done it myself but thinking about it for a bit made me think
that mocking the database for any kind of non-trivial testing will be
hard. For example, load() essentially instantiates the object from the
database. What will the mock version do in this case? In other words,
how would you implement:

void MockInstance::load(DatabaseEntity * pEntity)
{
   // Where does the information for pEntity's data members come from?
}

One thing that seem to make more sense is to use a special database
that is easier (transparent) to use in tests. For example, you could
use SQLite with an in-memory database (":memory:") which would be
completely private to the test. This way, for example, you could
run multiple tests in parallel without having to make sure they
don't trash the same set of data.

Just for completeness, if you still want to mock the database access
and don't want to use polymorphism support in ODB, then one way to
implement what you want would be to use compile-time rather than
runtime polymorphism. Something along these lines:

template <bool mock>
class DatabaseInstance;

template <>
class DatabaseInstance<true> // Mock.
{
  template <typename T>
  void load (T& x)
  {
    // Mock database load somehow...
  }
}

template <>
class DatabaseInstance<false> // Real.
{
  template <typename T>
  void load (T& x)
  {
    m_database->load (x.getId(), x);
  }
}

The main drawback of this approach is that you have to decide whether
you use mock access or the real stuff at compile time.

Boris



More information about the odb-users mailing list