title: How do I directly mock a superclass with python mock?
body: <p>I am using the python mock framework for testing (http://www.voidspace.org.uk/python/mock/) and I want to mock out a superclass and focus on testing the subclasses' added behavior.</p>
  
  <p>(For those interested I have extended <em>pymongo.collection.Collection</em> and I want to only test my added behavior.  I do not want to have to run mongodb as another process for testing purposes.)</p>
  
  <p>For this discussion, <em>A</em> is the superclass and <em>B</em> is the subclass.  Furthermore, I define direct and indirect superclass calls as shown below:</p>
  
  <pre><code>class A(object):
      def method(self):
          ...
  
      def another_method(self):
          ...
  
  class B(A):
      def direct_superclass_call(self):
          ...
          A.method(self)
  
      def indirect_superclass_call(self):
          ...
          super(A, self).another_method()
  </code></pre>
  
  <h2>Approach #1</h2>
  
  <p>Define a mock class for <em>A</em> called <em>MockA</em> and use <em>mock.patch</em> to substitute it for the test at runtime.  This handles direct superclass calls.  Then manipulate B.__bases__ to handle indirect superclass calls. (see below)</p>
  
  <p>The issue that arises is that I have to write <em>MockA</em> and in some cases (as in the case for <em>pymongo.collection.Collection</em>) this can involve a lot of work to unravel all of the internal calls to mock out.</p>
  
  <h2>Approach #2</h2>
  
  <p>The desired approach is to somehow use a mock.Mock() class to handle calls on the the mock just in time, as well as defined return_value or side_effect in place in the test.  In this manner, I have to do less work by avoiding the definition of MockA.</p>
  
  <p>The issue that I am having is that I cannot figure out how to alter B.__bases__ so that an instance of <em>mock.Mock()</em> can be put in place as a superclass (I must need to somehow do some direct binding here).  Thus far I have determined, that <em>super()</em> examines the MRO and then calls the first class that defines the method in question.  I cannot figure out how to get a superclass to handle the check to it and succeed if it comes across a mock class.  __getattr__ does not seem to be used in this case.  I want super to to think that the method is defined at this point and then use the mock.Mock() functionality as usual.</p>
  
  <p><strong>How does <em>super()</em> discover what attributes are defined within the class in the MRO sequence?  And is there a way for me to interject here and to somehow get it to utilize a <em>mock.Mock()</em> on the fly?</strong></p>
  
  <pre><code>import mock
  
  class A(object):
      def __init__(self, value):
          self.value = value      
  
      def get_value_direct(self):
          return self.value
  
      def get_value_indirect(self):
          return self.value   
  
  class B(A):
      def __init__(self, value):
          A.__init__(self, value)
  
      def get_value_direct(self):
          return A.get_value_direct(self)
  
      def get_value_indirect(self):
          return super(B, self).get_value_indirect()
  
  
  # approach 1 - use a defined MockA
  class MockA(object):
      def __init__(self, value):
          pass
  
      def get_value_direct(self):
          return 0
  
      def get_value_indirect(self):
          return 0
  
  B.__bases__ = (MockA, )  # - mock superclass 
  with mock.patch('__main__.A', MockA):  
      b2 = B(7)
      print '\nApproach 1'
      print 'expected result = 0'
      print 'direct =', b2.get_value_direct()
      print 'indirect =', b2.get_value_indirect()
  B.__bases__ = (A, )  # - original superclass 
  
  
  # approach 2 - use mock module to mock out superclass
  
  # what does XXX need to be below to use mock.Mock()?
  #B.__bases__ = (XXX, )
  with mock.patch('__main__.A') as mymock:  
      b3 = B(7)
      mymock.get_value_direct.return_value = 0
      mymock.get_value_indirect.return_value = 0
      print '\nApproach 2'
      print 'expected result = 0'
      print 'direct =', b3.get_value_direct()
      print 'indirect =', b3.get_value_indirect() # FAILS HERE as the old superclass is called
  #B.__bases__ = (A, )  # - original superclass
  </code></pre>