1

In our project we are using Google Mock, but in multiple places we are making contructions in our production code, only to make sure classes are "mockable". We do this because we want to have the benefits of Google Mock, but on the other side we would rather have more optimal production code. The following case is something we do often, and would like to get rid off.

class A{
  public:
    void doSomething(); //Does something with _someB
    void setSomeB(B* mockedB); //This is only here for GMock
  private:
    B* _someB; //This should not be a pointer, it is a pointer only for GMock
}

This is only a simplified example as you can see, I left out the details. Basically we want to get rid of B being a pointer. The reason we have it as a pointer, is that we can subclass B in our test code (mock it) and set it with that setter.

Is there any way to avoid this? Can't we let B be scoped in the class?

Thanks

W. Goeman
  • 1,674
  • 2
  • 15
  • 31
  • @TonyTheLion, that still wont make the object live on the stack, it will still be a pointer, and I would still need the setter. – W. Goeman Apr 06 '12 at 10:23
  • 1
    Google's quite the fan of dependency injection. It makes sense that you'd have a tough time using their testing framework without it. I'd highly encourage you to check out their YouTube video series "The Clean Code Talks". The one that covered the basics of their unit testing philosophy can be found here: http://youtu.be/wEhu57pih5w – cgmb Apr 10 '12 at 08:38
  • You could let the client of class `A` create `B` on the stack and then dependency inject it into class `A` as a reference. Also, when you say "optimal production code" is this premature optimization? – User Apr 26 '12 at 21:00

1 Answers1

1

If you really don't want _someB held as a pointer, an option would be to wrap its declaration in preprocessor commands:

#ifdef MOCK_TEST
    B _someB;
#else
    MockB _someB;
#endif

If you don't, there's no easy way to place gmock expectations and/or assertions on _someB, since it will not be an instance of a mock object. Apart from the ugliness of this, it also has the disadvantage of requiring the lib in which Class A resides to be compiled twice, once with MOCK_TEST defined and once without. It does however do away with the need for a setter for _someB.

Even if you choose to keep _someB as a pointer, perhaps a better option than creating a public setter is to declare the test class a friend class of A's to allow the test to directly set and access _someB.


As an aside, it's often considered poor form to name variables with a leading underscore.

Community
  • 1
  • 1
Fraser
  • 74,704
  • 20
  • 238
  • 215
  • It is indeed a good way to work around the setter, but it still requires "special" code in the class which the what I wanted to get rid of all along. I guess there is just no perfect solution for this problem. I will accept this answer is it gives a "reasonable" solution. Thanks for the leading underscore comment. I will certainly remember that one! – W. Goeman Apr 08 '12 at 19:37
  • 1
    @W.Goeman: as a followup to the leading underscore issue, note that the [Google C++ Style Guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Variable_Names) recommends trailing underscores. – User Apr 26 '12 at 21:02