Home > Back-end >  How to test several interface implementations with different constructors with gtest in C ?
How to test several interface implementations with different constructors with gtest in C ?

Time:07-22

I have an interface for which I have three implementations. I am using the TYPED_TEST from google test so that I can use the same set of tests for all implementations. I have the following Fixture.

template <typename T>
class GenericTester : public ::testing::Test {
  protected:
    T test_class;
};

I added the implementation types below.

using TestTypes = ::testing::Types<ImplementationOne, ImplementationTwo>
TYPED_TEST_SUITE(GenericDiffTester, DiffTypes);

So far, everything works fine, but now I have added another implementation. The difference between the last implementation is that its constructor requires taking a std::string as an argument, whereas the first two can be default constructed.

Now when I add this third interface, it does not compile.

using TestTypes = ::testing::Types<ImplementationOne, ImplementationTwo, ImplementationThree>
TYPED_TEST_SUITE(GenericDiffTester, DiffTypes);

Obviously, the problem is that the fixture requires test_class to be default constructible, which does not apply to ImplementationThree.

How can I initialize the templated member variable of a class depending on the provided type T? I want to default construct test_class if T is of type ImplementationOne or ImplementationTwo. Otherwise, I want to construct it as ImplementationThree with a string.

Is there a way to do it directly with Gtest without a hacky solution?

CodePudding user response:

The easiest way is to derive from your non-default constructible class. That derived class could be default constructible:

class TestableImplementationThree : public ImplementationThree
{
public:
    TestableImplementationThree() :
            ImplementationThree("dummy")
    {} 
};

And:

using TestTypes = ::testing::Types<
    ImplementationOne, 
    ImplementationTwo, 
    TestableImplementationThree>;

If you like to test ImplementationThree with different constructor argument - then just create and test as many testable-classes as needed.

if you do insist on testing exactly ImplementationThree - then wrap all classes with some kind of holders. For ImplementationThree specialize its "holder" to construct it differently.

template <typename T>
struct Holder
{
    T tested_object; 
};

template <>
struct Holder<ImplementationThree>
{
    ImplementationThree tested_object{"dummy"}; 
};

template <typename T>
class GenericTester : public ::testing::Test,
        protected Holder<T>
{
};


  • Related