Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have a class Base that has several children, say A, B, C. For testing purposes I'd like to mock those derived classes by deriving from them. So MockA derives from A, MockB derives from B and so on.

The problem is, that MockA, MockB, ... all inherit protected members from Base that have to be set in the same way in each mock class. The code looks like this:

MockA::init()
{
    x = 1;     // inherited from Base
    y = "abc"; // inherited from Base
    z = 0.5;   // inherited from Base
}

MockB::init()
{
    x = 1;     // inherited from Base
    y = "abc"; // inherited from Base
    z = 0.5;   // inherited from Base
}

and so on.

So my question is, how can I avoid this cut&paste initialization? Can I achieve it without touching Base, A, B, C, ...?

share|improve this question

4 Answers 4

up vote 5 down vote accepted

You want a "mixin". In C++ they are usually implemented with templates and specifically using CRTP, the "curiously recurring template pattern". It might be an overkill if it's just a bit of common code, than Pierre's answer seems most appropriate. But as the amount of common code for the mock classes grows, so will value of template.

Basic CRTP would go like this:

template <typename ConcreteT> class Mock {
    initMock() {
        static_cast<ConcreteT *>(this)->x = 1;
        static_cast<ConcreteT *>(this)->y = "abc";
        static_cast<ConcreteT *>(this)->z = 0.5;
    }
};

class MockA : A, Mock<MockA> { ... };
//                    ^^^^^ specialized on the type that inherits it, that's the point

Here it would make things simple to inherit A through the Mock class though, so

template <typename BaseT> class Mock : public BaseT {
    initMock() {
        x = 1;
        y = "abc";
        z = 0.5;
    }
};

class MockA : Mock<A> { ... };
//                 ^ just the base class

That does away with the ugly static_casts, but does not allow you to provide methods in MockA that will be called by Mock. But you can have both...

template<typename ConcreteT, typename BaseT>
class Mock : public BaseT { ... };

class MockA : Mock<MockA, A> { ... };

Now Mock can call methods of MockA on itself via static cast and call methods of A (or rather the ultimate base) directly.


Note: The mixin templates are basically the same thing as mixins in Ruby or interfaces with method implementations introduced in Java 8. Those languages it is a special construct, because they don't have anything of the power of C++ templates, but the implementation is similar—an intermediate class is constructed by compiler and injected in the hierarchy.

share|improve this answer
    
Uh, I hope I understand that correctly. So if I want MockA to be derived from A, I have to go for the first version, right? –  TobiMcNamobi May 16 '13 at 11:21
    
No wait, Base is a template parameter, not the actual Base class. Aha, so by inheriting from Mock<A> MockA DOES inherit from A. –  TobiMcNamobi May 16 '13 at 11:33
    
Pierre's answer simply does not work, see my comment below. If my answer is not applicable (because A,B,C and their base class cannot be changed, not even a line, under no circumstances), then I guess your solution is the best option. Thus +1. –  Doc Brown May 16 '13 at 15:33
    
@TobiMcNamobi: I've suffixed all template parameter names with T to disambiguate them. Yes, by inheriting Mock<A> you are indirectly inheriting A, only single inheritance involved. –  Jan Hudec May 17 '13 at 7:00

Well, you could introduce a static method which returns a default set of all protected member values and fetch them in each init method into the fields of the mock objects.

Edit:

MockA::init()
{
  initMock(MockInitializer.getDefaultValues());
  //go on with your code
}

MockA::initMock(anystruct def_values)
{
  //assign your values
}

The problem is that in any place you'll have to do the assignment, why not do it in its own method?

share|improve this answer
    
This default set is a struct / data class? Well, yes, at least the data is then the same for all mock classes. But still the "fetch into the fields" part will always look alike in every mock class. I would rather prefer a solution where the initialization shrinks down to one line. –  TobiMcNamobi May 16 '13 at 9:17
    
So initMock() will be the same in MockA, MockB, MockC? –  TobiMcNamobi May 16 '13 at 9:28
    
yes it will at least when the assigned variables are the same! –  McMannus May 16 '13 at 9:35
    
@Pierre Fourgeaud what if the default values differ for MockA and MockB? –  McMannus May 16 '13 at 9:42
    
At the moment I have something similar in fact. But I'm not satisfied with this because the code repetition is, in fact, still there. It's just different lines that are repeated. –  TobiMcNamobi May 16 '13 at 9:55

Here is how i would to that if I understand your problem :


class Base
{
protected:
    initMock()
    {
        x = 1;
        y = "abc";
        z = 0.5;
    }
};

class A { /* Whatever you want ... */ };

class B { /* Whatever you want ... */ };

class MockA : public A, public Base
{
public:
    initMock()
    {
         Base::initMock();
    }

};

And you can do the same thing with MockB.

share|improve this answer
1  
I think we are quite close here. What I like is that this construct is easily extended. Add classes C, D, E - no problem. Add MockWhatever - no effort. The only thing that bothers me is the initMock() method inside Base. This is code for testing inside a production class ... –  TobiMcNamobi May 16 '13 at 9:52
    
@MacMannus But what I understand here is that the initialization code will not differ right ? If not you can still add in MockA::initMock after the call to Base::initMock() something like x = 3; if you want a different value for a particular child. –  Pierre Fourgeaud May 16 '13 at 10:03
1  
@TobiMcNamobi If you don't want the initMock method in the base class, the only other solution I see to do it in the same way is to create another class like class BaseMock who contains the initMock method and everything else common to every Mock... –  Pierre Fourgeaud May 16 '13 at 10:06
    
Sounds reasonable. Normally I try to avoid multiple inheritance whereever possible. But maybe this is not the normal case ;-) –  TobiMcNamobi May 16 '13 at 10:39
    
It seems to me the initialization code is specific to the A/B derived classes, so they should have methods for initialization and your MockA should call A's initialization method which A normally calls. I'm with @TobiMcNamobi on the putting test code in production code is a huge no-no. –  Jimmy Hoffa May 16 '13 at 11:02

If Base is the common base class of A, B, C holding protected members Base::x, Base::y, etc., then I guess there are accessor methods like

Base::SetX(type_x xval){x=_val;}

etc. So write a static function in a helper class MockInit

void MockInit::initForTests(Base &b)
{
    b.SetX(1);
    b.SetY("abc");
    b.SetZ(0.5);
}

and call that function this way:

MockA::init()
{
     MockInit::initForTests(*this);
}

MockB::init()
{
     MockInit::initForTests(*this);
}

That's it - simple and stupid. However, if there are no such accessor methods, and you have you have absolutely no access to x,y,z from outside the inheritance hierarchy, I would consider changing the initial design of Base for better testability. At least, I would consider to make MockInit a friend class of Base.

share|improve this answer
    
Unfortunately the protected members have getters only but no setters. –  TobiMcNamobi May 16 '13 at 12:22
    
@TobiMcNamobi: outside of your testing code, x,y,z must be initialized somehow, too. Why can't you use that mechanism for testing purposes, too? –  Doc Brown May 16 '13 at 12:26
    
A, B, C, and Base are legacy code. At the moment I don't want to change these classes because I'm writing unit tests for a class that just uses A, B, C. Now A, B, C are initialing themselves by accessing a database. Of course for unit testing this is not an option, so that's why I have the need for MockA, MockB, MockC. –  TobiMcNamobi May 16 '13 at 13:18
    
@TobiMcNamobi: legacy code for which you have the source code available, or legacy code only available as binary + headers? The first case gives you much more options, introducing a line like friend class MockInit into your common Base class is a low-risk change which enables much easier testing testing. –  Doc Brown May 16 '13 at 13:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.