Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking boolean __bool__ protocol method in Python 2.7

As part of my unittests, I am testing some responses using the fantastic Requests library. Something cool you can do with this library is test a response for a 200 OK status code by simply calling:

r = requests.get("http://example.com")
if r:
    # success code, do something...
else:
    # error code, handle the error.

The way this works behind the scenes is Requests updates the __bool__() protocol method of the response returned according to the type of status code.

What I'd like to do is to be able to mock the response object of requests.get() well enough so that I can not only patch the methods/attributes I'm interested in checking (status_code, json()) but also to be able to return False whenever I choose to.

The following isn't working for me, as once I call r from the sample code above, it returns the Mock object <Mock id='2998569132'> which evaluates to True.

with mock.patch.object(requests, 'get', return_value=mock.MagicMock(
    # False, # didn't work
    # __bool__=mock.Mock(return_value=False), # throws AttributeError, might be Python2.7 problem
    # ok=False, # works if I call if r.ok: instead, but it's not what I want
    status_code=401,
    json=mock.Mock(
    return_value={
        u'error': {
            u'code': 401,
            u'message':
            u'Request had invalid authentication credentials.',
            u'status': u'UNAUTHENTICATED'
        }
    }
)
)) as mock_account_get_failure:
# mock_account_get_failure.return_value = False # overwrites what I just mocked with json() and status_code

I thought the answer might lie in Magic Mocking the protocol method's return value, but read here that __bool__ is only supported for Python 3.0.

like image 403
Peemster Avatar asked Nov 09 '22 00:11

Peemster


1 Answers

In python2.7, you should mock __nonzero__ instead of __bool__.

m = mock.MagicMock(__nonzero__=mock.Mock(return_value=False), status_code=400) m.status_code # > 400 bool(m) # > False

like image 130
ntrrobng Avatar answered Nov 14 '22 23:11

ntrrobng