Mocked object returning another Mocked object

Discussion in 'Python' started by Jean-Michel Pichavant, Jul 13, 2012.

  1. Greetings Fellow Group,


    I'd need your help to fix some issues I have with my unitary tests.
    I'm trying to bring them to the next level by Mocking equipments
    controlled by my application.

    Despite me reading http://www.voidspace.org.uk/python/mock/index.html I
    cannot figure out how to do the following :

    I have an App object with the 'target' attribute. This target is
    controlling a piece of hardware. The hardware itself holds a software,
    hence the target object having an 'api' attribute. I hope I make sense.

    So basically I'd like

    self.target.api.<anyMethod>()

    to return a Mocked object (Mocking an Api object response).



    ** Question **

    I do I make *all* method calls return a specifik Mock?

    target = Mock()

    result = target.api.start() # I'd like result to be a Mock I defined
    with the 'returnCode' attribute

    print result.returnCode
    1

    But I would like to do it for any method of api (the list is huge,
    setting each of them is not an option I think) so that in the end,

    result = target.api.start()
    result = target.api.stop()
    result = target.api.reset()
    result = target.api.loadSw()

    return all the same Mock object (with 'returnCode')


    Any idea ?

    Cheers,

    JM
    Jean-Michel Pichavant, Jul 13, 2012
    #1
    1. Advertising

  2. Am 13.07.2012 12:09, schrieb Jean-Michel Pichavant:
    > I have an App object with the 'target' attribute. This target is
    > controlling a piece of hardware. The hardware itself holds a software,
    > hence the target object having an 'api' attribute. I hope I make sense.
    >
    > So basically I'd like
    >
    > self.target.api.<anyMethod>()
    >
    > to return a Mocked object (Mocking an Api object response).
    >
    > ** Question **
    >
    > I do I make *all* method calls return a specifik Mock?
    >
    > target = Mock()
    >
    > result = target.api.start()


    I'm not sure where the "target" here comes in. As I understand it, the
    goal is to write the "api" object so that you can call any function on it...

    > I'd like result to be a Mock I defined
    > with the 'returnCode' attribute
    >
    > print result.returnCode
    > 1


    ....and every function should just return the same return code. Right?


    > But I would like to do it for any method of api (the list is huge,
    > setting each of them is not an option I think) so that in the end,
    >
    > result = target.api.start()
    > result = target.api.stop()
    > result = target.api.reset()
    > result = target.api.loadSw()
    >
    > return all the same Mock object (with 'returnCode')


    There are two options I could think of:

    1. Intercept attribute lookup

    From the top of my head, the syntax is something like this:

    class TargetMock(object):
    def __getattr__(self, name):
    def default_result(*vargs, **kwargs):
    return ReturnCode(1)
    return default_result

    This just ignores the name and returns a function returning the mock
    return code. I think you get the idea.


    2. Intercept individual lookups

    class TargetMock(object):
    def _default(self, *vargs, **kwargs):
    return ReturnCode(1)
    start = _default
    stop = _default
    reset = _default
    loadSW = _default

    Yes, this ignores your claim that the list of functions is too big to
    add every function individually. I'd just add them on demand when a test
    accesses a function that isn't there yet. The advantage is that it shows
    clearly which of the functions are just stubs if you actually implement
    a few of them differently.


    If the list functions is really that huge but you have a class (the real
    driver class) that defines this API, then you could extract this list
    programmatically. That way, you could also ensure that your mock API
    doesn't provide functions not supported by the original.


    Good luck!

    Uli
    Ulrich Eckhardt, Jul 13, 2012
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rico
    Replies:
    2
    Views:
    436
  2. Edward Diener
    Replies:
    2
    Views:
    273
    Edward Diener
    Aug 1, 2004
  3. Replies:
    11
    Views:
    646
    Christos Georgiou
    May 2, 2006
  4. Cs. Henk
    Replies:
    2
    Views:
    96
    Cs. Henk
    Mar 4, 2005
  5. Chuck Remes
    Replies:
    12
    Views:
    203
    Tony Arcieri
    Jul 7, 2010
Loading...

Share This Page