3. Actually, this is only happening because we’re using the
patch
decorator, which returns a
MagicMock
, an even
mockier version of
mock
that can also behave like a dictionary. More info in the
docs.
Let’s get the final test passing by retrieving the right user, and then we’ll have a look at
that surprise pass:
accounts/authentication.py (ch16l024-2).
if
response
.
json
()[
'status'
]
==
'okay'
:
return
User
.
objects
.
get
(
=
response
.
json
()[
'email'
])
…
OK
Beware of Mocks in Boolean Comparisons
So how come our
test_returns_none_if_response_errors
isn’t failing?
Because we’ve mocked out
requests.post
, the
response
is aMock object, which as you
remember, returns all attributes and properties as more Mocks.
3
So, when we do:
accounts/authentication.py.
if
response
.
json
()[
'status'
]
==
'okay'
:
response
is actually a mock,
response.json()
is a mock, and
response.json()['sta
tus']
is a mock too! We end up comparing a mock with the string “okay”, which eval‐
uates to False, and so we return None by default. Let’s make our test more explicit, by
saying that the response JSON will be an empty dict:
accounts/tests/test_authentication.py (ch16l025).
def
test_returns_none_if_response_errors
(
self
,
mock_post
):
mock_post
.
return_value
.
ok
=
False
mock_post
.
return_value
.
json
.
return_value
=
{}
user
=
self
.
backend
.
authenticate
(
'an assertion'
)
self
.
assertIsNone
(
user
)
That gives:
if response.json()['status'] == 'okay':
KeyError: 'status'
And we can fix it like this:
accounts/authentication.py (ch16l026).
if
response
.
ok
and
response
.
json
()[
'status'
]
==
'okay'
:
return
User
.
objects
.
get
(
=
response
.
json
()[
'email'
])
…
OK
Great! Our
authenticate
function is now working the way we want it to.
290
|
Chapter 16: Server-Side Authentication and Mocking in Python