[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Fundamental question: How to resolve dependencies with mock objects


Hi James,

looks like I wrote the mail to early. Chapter 9 of your book covers this
topic...

best regards,
Frank

> wp1186628-frank <frank@xxxxxxxxxxxxxxxx> hat am 27. Mai 2014 um 08:50
> geschrieben:
> 
>  Hi James, hi Jakub,
> 
>  thanks for the feedback. I misunderstood that I do not need wrapping to mock
> objects.
> 
>  James: At the moment I read your book, currently at chapter 8. Up to now, you
> only describe how to replace interaction to Hardware / OS, i.e. mock external
> modules that are not part of your project and you do not need to unit test at
> all.
>  But if I have a big system (with complex dependencies between its like
> typical for legacy code) and you want to unit test all the modules, I'm not
> really sure how to handle this. If I do use function pointers like you
> describe I fear ending up with a really complex and hard to understand test
> system, continously switching between fake and real implementation.
> 
>  More concrete, a first step I want to take is to implement Unit Tests for a
> Model-View-Controller implementation (in C). If I want to test each of the
> three modules seperately (M, V and C), I will need flexiblity to change
> between fake and real implementation for each of the three. So is the only way
> to do this "function pointer thing" to achieve this? Is cmocka the right
> framework for this or are there frameworks available that can do this nicely?
> 
>  best regards,
>  Frank
> 
> 
> 
> 
>   > > James Grenning <james@xxxxxxxxxxxx> hat am 21. Mai 2014 um 15:32
>   > > geschrieben:
> > 
> > 
> >   Markdown settings messed with my example code. Here it is again
> > 
> >   int (current_foo)(char c) = 0;
> > 
> >   int _fakefoo(char* c)
> >   {
> >   if (currentfoo)
> >   return currentfoo(c);
> > 
> >   return 42;
> > 
> >   }
> > 
> >   On 21 May 2014, at 7:47, James Grenning wrote:
> > 
> >       > > > 
> > >       You might want to implement _fakefoo with a function pointer. This
> > > way you can swap the implementation at runtime
> > > 
> > >       int (current_foo)(char c) = 0;
> > > 
> > >       int _fakefoo(char* c)
> > >       {
> > >       if (currentfoo)
> > >       return currentfoo(c);
> > > 
> > >       return 42;
> > > 
> > >       }
> > > 
> > > 
> > >       ---------------------------------------------
> > > 
> > >       James Grenning Author of TDD for Embedded C
> > >       <http://www.wingman-sw.com>
> > >       http://pragprog.com/titles/jgade/
> > >       <http://www.wingman-sw.com/blog>
> > > 
> > >       <http://www.twitter.com/jwgrenning>
> > > 
> > >       On 21 May 2014, at 7:27, Jakub Hrozek wrote:
> > > 
> > >           > > > > 
> > > >           Hi,
> > > > 
> > > >           mock and wrap are two different things. You can mock a
> > > > function
> > > >           without the wrap trick and vice versa. For instance, you can
> > > > mock a
> > > >           function like the cmocka example illustrates by providing the
> > > > full
> > > >           function prototype and returning the previously prepared
> > > > return code:
> > > > 
> > > >          http://git.cryptomilk.org/projects/cmocka.git/tree/example/customerdatabase_test.c#n38
> > > > 
> > > >           The wrapping is a linker feature that allows you to trick the
> > > > linker
> > > >           into calling wrapfoo() instead of foo(). You can always call
> > > > the
> > > >           "real" foo if you like, by calling _realfoo(). This might be
> > > > useful
> > > >           to check if foo() was called in the program under test for
> > > > instance.
> > > >           In SSSD we have something like:
> > > > 
> > > >           bool wasfoocalled;
> > > > 
> > > >           _realfoo(); /* You need the declaration */
> > > > 
> > > >           _wrapfoo()
> > > >           {
> > > >           wasfoocalled = true; /* Let the test driver know foo was
> > > > called /
> > > >           _realfoo(); / Call the original foo function */
> > > >           }
> > > > 
> > > >           You can even control whether to call the real foo or some
> > > > mocked
> > > >           version based on parameter you pass with willreturn in
> > > > advance. Here
> > > >           is some example from SSSD:
> > > > 
> > > >          https://git.fedorahosted.org/cgit/sssd.git/tree/src/tests/cmocka/testnss_srv.c#n89
> > > > 
> > > >           I hope this helps.
> > > > 
> > > >           On Wed, May 21, 2014 at 1:48 PM, Frank Lorenz
> > > > lorenz-frank@xxxxxx <mailto:lorenz-frank@xxxxxx> wrote:
> > > > 
> > > >               > > > > > 
> > > > >               Hi,
> > > > > 
> > > > >               starting to use unit tests for an existing project
> > > > > (embedded C), I currently
> > > > >               try to use cmocka for this.
> > > > >               I have a lot of dependencies (e.g. to hardware) and
> > > > > interfaces to other
> > > > >               devices that let me think I require mock objects to do a
> > > > > "simple simulation"
> > > > >               of hardware/interfaces for unit tests.
> > > > >               So I started to integrate cmocka and now have a lack of
> > > > > basic understanding
> > > > >               of the concept:
> > > > > 
> > > > >               As far as I understand, I need to implement a wrapper
> > > > > function for every
> > > > >               function I want to mock. As an example, for a mock of a
> > > > > function int
> > > > >               foo(char* c) I write a function int _wrapfoo ( char* c )
> > > > > and give
> > > > >               the option "--wrap=foo to the linker.
> > > > > 
> > > > >               My question is:
> > > > >               If I want to implement unit tests for two modules A and
> > > > > B, and I want to
> > > > >               have a mock version of B for unit test of A and a mock
> > > > > version of A for unit
> > > > >               test of B -- how to implement this?
> > > > >               Because when I implement mock versions of all functions
> > > > > of A and of B and
> > > > >               tell the linker to use these "wrappers" instead of the
> > > > > real functions, then
> > > > >               my unit test executable will only contain the mock
> > > > > versions of all the
> > > > >               functions. The "real" implementation of A and B will not
> > > > > be linked into the
> > > > >               executable and therefore cannot be tested.
> > > > >               Or do I miss something?
> > > > > 
> > > > >               best regards,
> > > > >               Frank
> > > > > 
> > > > >           > > > > 
> > > >       > > > 
> > >   > > 
> >  > 
> 
> 


Follow-Ups:
Re: Fundamental question: How to resolve dependencies with mock objects"James Grenning" <james@xxxxxxxxxxxx>