2

When running the test bellow, I got a stop called on unstarted patcher.

def test_get_subvention_internal_no_triggered_admission(self):
    billing_cluster = BillingClusterFactory()
    subvention = SubventionFactory(billing_cluster=billing_cluster)
    convive_sub = ConviveFactory(subvention=subvention, billing_cluster=billing_cluster)
    order_5 = OrderFactory(beneficiary=convive_sub)
    order_operation_5 = CreationOrderOperationFactory(order=order_5)

    with patch('orders.models.Order.subvention_triggered_same_day', return_value=True):
        with patch('builtins.hasattr', return_value=False):
            self.assertIsNone(order_operation_5._get_subvention())

I read stuff about this error on stack overflow, and concluded that I should avoid mocking the same stuff (stacked mocks). But it's not what I'm doing here. I'm nesting mocks, and it seems to be ok.

If I invert the return values (first mock returns False, second returns True), the test works well.

Any idea? Thanks.

David Dahan
  • 10,576
  • 11
  • 64
  • 137

1 Answers1

2

In short, you cannot patch the builtins func hasattr

patch('builtins.hasattr', return_value=False)

reason: used by mock.py

if not _is_started(self):
    raise RuntimeError('stop called on unstarted patcher')

def _is_started(patcher):
    # XXXX horrible
    return hasattr(patcher, 'is_local')

to repeat the error:

@mock.patch('__builtin__.hasattr')
def test_mock_hasattr(self, mocked_hasattr):
    # as long as it is set to False, it will trigger
    mocked_hasattr.return_value = False

to mock a builtins func inside models.py:

# narrow the mock scope
@mock.patch('orders.models.hasattr')
Gang
  • 2,658
  • 3
  • 17
  • 38
  • Thanks for the explanation. How come it's not specified in [Python mock doc](https://docs.python.org/3/library/unittest.mock.html)? Side question: any idea for a workaround? – David Dahan Mar 18 '18 at 10:30
  • @DavidD. eg https://stackoverflow.com/questions/30313134/write-test-for-views-containing-os-remove-in-django – Gang Mar 18 '18 at 13:10
  • Ahh I misunderstood your answer the first time. Makes more sense now. Thanks a lot ;) – David Dahan Mar 18 '18 at 15:10