jsatt / mock

Automatically exported from code.google.com/p/mock
BSD 2-Clause "Simplified" License
0 stars 0 forks source link

[enhancement] Passing base class(es) for mock instances #216

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
Hi,

I'd like to create regular mock instances but with overriding one or more 
methods. After some fiddling I came up with a hackish workaround but I was 
hoping it would be easier out of the box. Here's an example:

class Foo:
   def a(self):
      print "a!"
      self.x = 0
   def b(self, n):
      print "b!"
      self.y = 1 + n

from mock import Mock
m = Mock()
# XXX: need cleaner way to achieve this
m.__class__.__bases__ = (m.__class__.__base__, Foo)

m.a()       # print "a!""
print m.x   # print 0
m.b(2)      # print "b!" 
print m.y   # print 3
m.other()   # print <Mock name='mock.other()' id='48202448'>

Original issue reported on code.google.com by George.S...@fieldaware.com on 8 Nov 2013 at 11:54

GoogleCodeExporter commented 8 years ago
Why not just use patch or patch.object to attach your override methods to the 
class?

Original comment by fuzzyman on 14 Nov 2013 at 11:20

GoogleCodeExporter commented 8 years ago
Can you post an example of how the snippet above could be rewritten using 
patch/patch.object? I'm probably missing something but as far as I can tell 
from the docs and the examples, patch is useful for replacing an original 
attribute/method with a fake one. Here I do want to call the original a and b 
methods so that their side effects take place (print something, set 
self.x/self.y attributes). The only reason for using mock here is to fake 
everything *except* 'a' and 'b' (e.g. a mock 'other' method).

Original comment by George.S...@fieldaware.com on 15 Nov 2013 at 8:41

GoogleCodeExporter commented 8 years ago
mock.patch.object would require you to override individual methods on the 
class. To fake everything *except* a few methods is trickier (although you 
could do it with a factory function that iterates over all methods on a class 
and replaces them using patch.object).

Do you have a proposed api for this?

Original comment by fuzzyman on 18 Nov 2013 at 12:53

GoogleCodeExporter commented 8 years ago
I just realized a surprisingly simple way that works in my case: override the 
desired methods in a class that inherits from Mock (or MagicMock):

class Foo(object):
    def a(self): ...
    def b(self, n): ...
    def c(self, x, y): ...

class FooMock(MagicMock):
    def a(self):
       self.x = 0
    def b(self, n):
       self.y = 1 + n

m = FooMock()
m.a()           # calls FooMock.a
print m.x       # 0  
m.b(2)          # calls FooMock.b
print m.y       # 3
print m.c(3,4)  # mock object
print m.other() # mock object

So it doesn't seem necessary to introduce a new parameter after all.

Cheers,
George

Original comment by George.S...@fieldaware.com on 18 Nov 2013 at 9:53

GoogleCodeExporter commented 8 years ago
Ok, I'm glad that works for you.

Original comment by fuzzyman on 19 Nov 2013 at 3:22