a pastebin project

Stuff

  1. """
  2. Mock object implementation.
  3.  
  4. This mock object implementation is meant to be very forgiving - it returns a
  5. new child Mock Object for every attribute accessed, and a mock object is
  6. returned from every method call.
  7.  
  8. It is the tester's job to enabled the calls that they are interested in
  9. testing, all calls where the return value of the call and side effects are not
  10. recorded (logging, for example) are likely to succeed w/o effort.
  11.  
  12. If you wish to call the actual implementation of a function on a MockObject,
  13. you have to enable it using enableMethod.  If you wish to use an actual variable setting, you need to set it.
  14.  
  15. All enabling/checking methods for a MockObject are done through the _mock attribute.  Example:
  16.  
  17. class Foo(object):
  18.     def __init__(self):
  19.         # NOTE: this initialization is not called by default with the mock
  20.         # object.
  21.         self.one = 'a'
  22.         self.two = 'b'
  23.  
  24.     def method(self, param):
  25.         # this method is enabled by calling _mock.enableMethod
  26.         param.bar('print some data')
  27.         self.printMe('some other data', self.one)
  28.         return self.two
  29.  
  30.     def printMe(self, otherParam):
  31.         # this method is not enabled and so is stubbed out in the MockInstance.
  32.         print otherParam
  33.  
  34. def test():
  35.     m = MockInstance(Foo)
  36.     m._mock.set(two=123)
  37.     m._mock.enableMethod('method')
  38.     param = MockObject()
  39.     rv = m.method(param)
  40.     assert(rv == 123) #m.two is returned
  41.     # note that param.bar is created on the fly as it is accessed, and
  42.     # stores how it was called.
  43.     assert(param.bar._mock.assertCalled('print some data')
  44.     # m.one and m.printMe were created on the fly as well
  45.     # m.printMe remembers how it was called.
  46.     m.printMe._mock.assertCalled('some other data', m.one)
  47.     # attribute values are generated on the fly but are retained between
  48.     # accesses.
  49.     assert(m.foo is m.foo)
  50.  
  51. TODO: set the return values for particular function calls w/ particular
  52. parameters.
  53. """
  54. import new
  55.  
  56.  
  57. class MockObject(object):
  58.     """
  59.         Base mock object.
  60.  
  61.         Creates attributes on the fly, affect attribute values by using
  62.         the _mock attribute, which is a MockManager.
  63.  
  64.         Initial attributes can be assigned by key/value pairs passed in.
  65.     """
  66.  
  67.     def __init__(self, **kw):
  68.         self._mock = MockManager(self)
  69.         self.__dict__.update(kw)
  70.         self._mock._dict = {}
  71.  
  72.     def __getattribute__(self, key):
  73.         if key == '_mock' or self._mock.enabled(key):
  74.             return object.__getattribute__(self, key)
  75.         if key in self.__dict__:
  76.             return self.__dict__[key]
  77.         m = self._mock.getCalled(key)
  78.         self.__dict__[key] = m
  79.         return m
  80.  
  81.     def __setattr__(self, key, value):
  82.         if key == '_mock' or self._mock.enabled(key):
  83.             object.__setattr__(self, key, value)
  84.         else:
  85.             m = self._mock.setCalled(key, value)
  86.             if not hasattr(self, key):
  87.                 object.__setattr__(self, key, m)
  88.  
  89.     def __setitem__(self, key, value):
  90.         m = self._mock.setItemCalled(key, value)
  91.         self._mock._dict[key] = m
  92.  
  93.     def __len__(self):
  94.         return self._mock.length
  95.  
  96.     def __iter__(self):
  97.         for i in range(len(self)):
  98.             yield self[i]
  99.  
  100.     def __getitem__(self, key):
  101.         if key in self._mock._dict:
  102.             return self._mock._dict[key]
  103.         else:
  104.             m = self._mock.getItemCalled(key)
  105.             self._mock._dict[key] = m
  106.             return m
  107.  
  108.     def __hasattr__(self, key):
  109.         if key == '_mock' or self._mock.enabled(key):
  110.             return object.__hasattr__(self, key)
  111.         return True
  112.  
  113.     def __call__(self, *args, **kw):
  114.         return self._mock.called(args, kw)
  115.  
  116. class MockManager(object):
  117.     def __init__(self, obj):
  118.         self._enabledByDefault = False
  119.         self._enabled = set(['__dict__', '__methods__', '__class__',
  120.                              '__members__'])
  121.         self._disabled = set([])
  122.         self._errorToRaise = None
  123.         self.calls = []
  124.         self.callReturns = []
  125.         self.getCalls = []
  126.         self.setCalls = []
  127.         self.getItemCalls = []
  128.         self.setItemCalls = []
  129.         self.hasCalls = []
  130.         self.eqCalls = []
  131.         self.obj = obj
  132.         self.superClass = object
  133.         self.length = 1
  134.  
  135.     def enableByDefault(self):
  136.         self._enabledByDefault = True
  137.  
  138.     def disableByDefault(self):
  139.         self._enabledByDefault = False
  140.  
  141.     def setReturn(self, returnValue, *args, **kw):
  142.         self.callReturns.append((args, tuple(sorted(kw.items())), returnValue))
  143.  
  144.     def enableMethod(self, name):
  145.         """
  146.             Enables a method to be called from the given superclass.
  147.  
  148.             The function underlying the method is slurped up and assigned to
  149.             this class.
  150.         """
  151.         self.enable(name)
  152.         func = getattr(self.superClass, name).im_func
  153.         method = new.instancemethod(func, self.obj, self.obj.__class__)
  154.         object.__setattr__(self.obj, name, method)
  155.  
  156.     def enable(self, *names):
  157.         self._enabled.update(names)
  158.         self._disabled.difference_update(names)
  159.  
  160.     def disable(self, *names):
  161.         self._enabled.difference_update(names)
  162.         self._disabled.update(names)
  163.         for name in names:
  164.             object.__setattr__(self.obj, name, MockObject())
  165.  
  166.     def enabled(self, name):
  167.         if self._enabledByDefault:
  168.             return name not in self._disabled
  169.         else:
  170.             return name in self._enabled
  171.  
  172.     def set(self, **kw):
  173.         for key, value in kw.iteritems():
  174.             self._enabled.add(key)
  175.             setattr(self.obj, key, value)
  176.  
  177.     def raiseErrorOnAccess(self, error):
  178.         self._errorToRaise = error
  179.  
  180.     def assertCalled(self, *args, **kw):
  181.         kw = tuple(sorted(kw.items()))
  182.         assert((args, kw) in self.calls)
  183.         self.calls.remove((args, kw))
  184.  
  185.     def assertNotCalled(self, *args, **kw):
  186.         assert(not self.calls)
  187.  
  188.     def setCalled(self, key, value):
  189.         if self._errorToRaise:
  190.             self._raiseError()
  191.         m = MockObject()
  192.         self.setCalls.append((key, value, m))
  193.         return m
  194.  
  195.     def setItemCalled(self, key, value):
  196.         if self._errorToRaise:
  197.             self._raiseError()
  198.         m = MockObject()
  199.         self.setItemCalls.append((key, value, m))
  200.         return m
  201.  
  202.  
  203.     def _raiseError(self):
  204.         err = self._errorToRaise
  205.         self._errorToRaise = None
  206.         raise err
  207.  
  208.     def getCalled(self, key):
  209.         if self._errorToRaise:
  210.             self._raiseError()
  211.         m = MockObject()
  212.         self.getCalls.append((key, m))
  213.         return m
  214.  
  215.     def getItemCalled(self, key):
  216.         if self._errorToRaise:
  217.             self._raiseError()
  218.         m = MockObject()
  219.         self.getItemCalls.append((key, m))
  220.         return m
  221.  
  222.  
  223.     def called(self, args, kw):
  224.         kw = tuple(sorted(kw.items()))
  225.         self.calls.append((args, kw))
  226.         if self._errorToRaise:
  227.             self._raiseError()
  228.         else:
  229.             rv = [x[2] for x in self.callReturns if (x[0], x[1]) == (args, kw)]
  230.             if rv:
  231.                 return rv[-1]
  232.             else:
  233.                 return MockObject()
  234.  
  235.     def getCalls(self):
  236.         return self.calls
  237.  
  238.     def popCall(self):
  239.         call =  self.calls[0]
  240.         self.calls = self.calls[1:]
  241.         return call
  242.  
  243. class MockInstance(MockObject):
  244.  
  245.     def __init__(self, superClass, **kw):
  246.         MockObject.__init__(self, **kw)
  247.         self._mock.superClass = superClass
  248.  
  249. def attach(obj):
  250.     if hasattr(obj, '__setattr__'):
  251.         oldsetattr = obj.__setattr__
  252.     if hasattr(obj, '__getattribute__'):
  253.         oldgetattr = obj.__getattribute__
  254.  
  255.     def __setattr__(self, key, value):
  256.         if not isinstance(getattr(self, key), mock.MockObject()):
  257.             oldsetattr(key, value)
  258.  
  259.     def __getattribute__(self, key):
  260.         if not hasattr(self, key):
  261.             oldsetattr(key, mock.MockObject())
  262.         return oldgetattr(key)
  263.     oldsetattr('__setattr__', new.instancemethod(__setattr__, obj,
  264.                                                  obj.__class__))
  265.     oldsetattr('__getattribute__', new.instancemethod(__getattribute__, obj, obj.__class__))
  266.  
  267. def mockMethod(method):
  268.     self = method.im_self
  269.     name = method.__name__
  270.     origMethod = getattr(self, name)
  271.     setattr(self, name, MockObject())
  272.     getattr(self, name)._mock.method = origMethod
  273.     getattr(self, name)._mock.origValue = origMethod
  274.  
  275. def mock(obj, attr):
  276.     m = MockObject()
  277.     if hasattr(obj, attr):
  278.         m._mock.origValue = getattr(obj, attr)
  279.     setattr(obj, attr, m)
  280.  
  281. def mockClass(class_, *args, **kw):
  282.     commands = []
  283.     runInit = kw.pop('mock_runInit', False)
  284.     for k, v in kw.items():
  285.         if k.startswith('mock_'):
  286.             if not isinstance(v, (list, tuple)):
  287.                 v = [v]
  288.             commands.append((k[5:], v))
  289.             kw.pop(k)
  290.     class _MockClass(MockInstance, class_):
  291.         def __init__(self, *a, **k):
  292.             MockInstance.__init__(self, class_, *args, **kw)
  293.             if runInit:
  294.                 self._mock.enableByDefault()
  295.                 class_.__init__(self, *a, **k)
  296.             self._mock.called(a, k)
  297.             for command, params in commands:
  298.                 getattr(self._mock, command)(*params)
  299.  
  300.     return _MockClass
  301.  
  302. def mockFunctionOnce(obj, attr, returnValue):
  303.     newFn = lambda *args, **kw: returnValue
  304.     return replaceFunctionOnce(obj, attr, newFn)
  305.  
  306. def replaceFunctionOnce(obj, attr, newFn):
  307.     curValue = getattr(obj, attr)
  308.     def restore():
  309.         setattr(obj, attr, curValue)
  310.  
  311.     def fun(*args, **kw):
  312.         restore()
  313.         return newFn(*args, **kw)
  314.     setattr(obj, attr, fun)
  315.     fun.func_name = attr
  316.     fun.restore = restore

advertising

Create a Paste

Please enter your new post below (or upload a file instead):





Please note that information posted here will not expire by default. If you want it to expire, please set the expiry time above. If it is set to expire, web search engines will not be allowed to index it prior to it expiring. Items that are not marked to expire will be indexable by search engines. Be careful with your passwords.

worth-right
fantasy-obligation