title: How do I turn my StripeMockSubscription class into a true and proper unittest.mock MagicMock
body: <p>In search of a fast stripe mock that didn't require an extra server to be running and produced realistic enough responses to use,  I built the following class which works, but which is missing some functionality of the MagicMock, things like <code>assertCalledWith</code>, <code>assertCalledOnce</code></p>
  <p>I'm using this Mock class like so:</p>
  <pre><code>@mock.patch('stripe.Subscription', new_callable=StripeMockSubscription)
  def test_something(self, _): #because the mock doesn't behaving like a MagicMock
  </code></pre>
  <p>But I would prefer to use it like:</p>
  <pre><code>@mock.patch('stripe.Subscription', new_callable=StripeMockSubscription)
  def test_something(self, subscription_mock: mock.MagicMock):
  </code></pre>
  <p>but for that to work I need to figure out how to give the mock class MagicMock powers to track calls, parameters, etc... so that I get the side effects AND I get the MagicMock behavior.</p>
  <p>It is possible to just mock out each method but then you end up with a stack of mocks on the top of the test that borders on unreadable. (Yes, I know you can put them on the test class, but you still have to enumerate all the arguments and if you don't need a mock on a specific test then you have unused parameters. (thanks for nothing pylint))</p>
  <h2>TLDR;</h2>
  <p>This is one of several classes for mocking out a portion of the stripe API, How do I turn this into something that also has the behavior of MagicMock on each of the methods? ie
  <code>subscription_mock.retrieve.assertCalledOnce()</code></p>
  <pre><code>class StripeMockSubscription(real_stripe.Subscription):
      &quot;&quot;&quot; Mimics stripe.Subscription.* sort of.  The @classmethod is from the actual stripe
        API library &quot;&quot;&quot;
  
      @classmethod
      def retrieve(cls, id: str, api_key=None, **kwargs):
          subscription = Subscription.objects.for_stripe_test_fixtures().get(stripe_id=id)
          context = {
              'sub': subscription,
              'schedule': 'null',
          }
  
          schedule = Schedule.objects.filter(subscription=subscription).first()
          if schedule:
              context['schedule'] = mark_safe(f&quot;\&quot;{schedule.schedule['id']}\&quot;&quot;)
  
          if subscription.paid_until:
              context.update({
                  'start_date': subscription.paid_until-timedelta(days=subscription.price.period_in_days),
                  'end_date': subscription.paid_until,
              })
          else:
              context.update({
                  'start_date': timezone.now(),
                  'end_date': timezone.now()+timedelta(days=subscription.price.period_in_days),
              })
  
          sub = load_template_fixture('subscription.json', context=context)
          sub['url'] = 'https://stripe.com/goto-here/'
          # self['updated'] = 0
  
          return real_stripe.Subscription.construct_from(values=sub, key='FakeAPIKey')
  
      @classmethod
      def modify(cls, sid, **params):
          &quot;&quot;&quot; TODO: This could be better, for right now we just fake it until we make it! &quot;&quot;&quot;
          return StripeModifyResponse()(sid, **params)
  
      @classmethod
      def create(cls, sid, **params):
          &quot;&quot;&quot; TODO: This could be better, for right now we just fake it until we make it! &quot;&quot;&quot;
          return StripeCreateResponse()(sid, **params)
  </code></pre>