home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 32,788 of 33,346   
   Ian Collins to from the database and   
   Re: Unit Testing Frameworks (was Re: Sin   
   10 Jan 13 21:30:48   
   
   l-september.org> 10cf4d62   
   From: ian-news@this.is.invalid   
      
   Tobias Müller wrote:   
   > Ian Collins  wrote:   
   >> Tobias Müller wrote:   
   >>>   
   >>> Öö Tiib  wrote:   
   >>>> It has been several times asked in this thread: Why it is   
   >>>> difficult to create fake Singleton::instance() that is   
   >>>> instrumented to return an mock object that you want? Usual answer   
   >>>> has been repeated "clear and obvious" fact that DI is somehow   
   >>>> simpler. Ok, but why and how?   
   >>>   
   >>> Usually, you test the external interface of a class if it behaves   
   >>> the way it has to. The use of a singleton in the class is an   
   >>> implementation detail and may thus easily be forgotten to test.   
   >>   
   >> How can you test the behaviour of a class without testing how it   
   >> interacts its environment?  You most certainly can't if you develop   
   >> test first.   
   >   
   > That's the point exactly. With DI you make clear which parts of the   
   > environment you are actually using.   
      
   Maybe, but setting up a mock to enable a test should also make it   
   clear.   
      
   >>> With DI, you the "singleton" is part of the public interface of   
   >>> the class and can be tested without making assumptions on the   
   >>> internals of the class.   
   >>   
   >> The internals of which class?   
   >   
   > The one under test.   
   >   
   >> If you are testing how the class under test uses the singleton, the   
   >> internals of the real singleton are irrelevant.   
   >   
   > Yes of course.   
   >   
   >> Your task is to check whether (and how) the appropriate member   
   >> functions are called and the behaviour of your code to given return   
   >> values.   
   >   
   > Same question, do you mean the members of the class under test or   
   > the singleton?   
   >   
   > If you mean the singleton, then I disagree. It's rarely specified   
   > that a class must call some specific singleton methods in a specific   
   > way.   
      
   Well the function under test has to get its data from somewhere.  A   
   prime example would be a test along the lines of "test some function   
   increments some database value".  Obviously the test will have to read   
   from the database and write back to it.   
      
   > For example you have a configuration singleton. All classes in your   
   > project can use it if they want. But they don't have to. It's up to   
   > the implementor of the class. In the best case it is specified   
   > documented if the class uses the configuration. In the worst case   
   > the documentation is wrong or outdated. If it's not documented you   
   > have to guess or look at the code.   
      
   Unit tests can't be wrong or outdated! As I said above, setting up a   
   mock to enable a test should also make it clear.   
      
   >> To do this, you either have to jump through hoops of fire to   
   >> instrument the real code, or use a mock.   
   >   
   > Same for DI, but it's much easier to substitute the real code with   
   > the mock when using DI.   
      
   Here we go go again: why?   
      
   I've never found that to be the case.  The two are equally complex or   
   simple.  I'm not advocating singletons over DI, I'm just objecting   
   (based on my experience) to this one point and all of its   
   ramifications.   
      
   >>> With DI you have to specify an interface for those "singletons"   
   >>> that may be injected, with a real singleton one is tempted to just   
   >>> create, use and modify it ad hoc. A well defined interface is   
   >>> always good for testing.   
   >>   
   >> Eh?  A singleton is no different from any other class form a   
   >> testing perspective.   
   >   
   > A singleton is often designed with the assumption that there's only   
   > one class/instance anyway, so one tends to be a bit sloppier. Need a   
   > new method? Just add one, not much to think about.   
      
   Whether something like a database instance is a implemented as a   
   classical singleton, or a one off object passed around, there's only   
   one instance of it, isn't there?  If it walks like a duck and quacks   
   like a duck....   
      
   > With DI this is different. You rely on polymorphism (compile time   
   > via templates or runtime via interfaces). There you cannot just   
   > change something without breaking code.   
      
   If you write decent tests, whether you use a singleton or DI, you   
   cannot change something without breaking tests.   
      
   >>> Of course you can replace a singleton with a mock if you really   
   >>> want to.  But you cannot just take you library and build a test   
   >>> application around it. You have to exclude the complete singleton   
   >>> implementation from the original code and replace it with a   
   >>> different one.   
   >>   
   >> Isn't that what mocking is all about?  At least in my world   
   >> everything that isn't part of the unit under test is mocked. That's   
   >> why we have mocking frameworks to do the donkey work for us.   
   >   
   > The difference is, that with DI the real code can still be around,   
   > just not used. With a singleton however, only one can exist at a   
   > time.   
      
   What's the point of having the real code around in your tests?  You   
   just make the whole test situation that much more complex.  Is the   
   test using a mock or the real code?   
      
   --   
   Ian Collins   
      
      
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca