![Show Menu](styles/mobile-menu.png)
![Page Background](./../common/page-substrates/page0307.png)
2. Even though we’re going to define our own
authenticate
function, we still import from
django.con
trib.auth
. Django will dynamically replace it with our function once we’ve configured it in
settings.py
. This
has the benefit that, if we later switch to a third-party library for our
authenticate
function, our views.py
doesn’t need to change.
The decorator called
patch
is a bit like the Sinon
mock
function we saw in the
last chapter. It lets you specify an object you want to “mock out”. In this case
we’re mocking out the
authenticate
function, which we expect to be using in
accounts/views.py
.
The decorator adds the mock object as an additional argument to the function
it’s applied to.
We can then configure the mock so that it has certain behaviours. Having
au
thenticate
return
None
is the simplest, so we set the special
.return_value
attribute. Otherwise it would return another mock, and that would probably
confuse our view.
Mocks canmake assertions! In this case, they can check whether they were called,
and what with.
So what does that give us?
$
python3 manage.py test accounts
[...]
AttributeError: <module 'accounts.views' from
'/workspace/superlists/accounts/views.py'> does not have the attribute
'authenticate'
We tried to patch something that doesn’t exist yet. We need to import
authenticate
into our
views.py
:
2
accounts/views.py.
from
django.contrib.auth
import
authenticate
Now we get:
AssertionError: Expected 'authenticate' to be called once. Called 0 times.
That’s our expected failure; to implement, we’ll have to wire up a URL for our login view:
superlists/urls.py.
urlpatterns
=
patterns
(
''
,
url
(
r'^$'
,
'lists.views.home_page'
,
name
=
'home'
),
url
(
r'^lists/'
,
include
(
'lists.urls'
)),
url
(
r'^accounts/'
,
include
(
'accounts.urls'
)),
# url(r'^admin/', include(admin.site.urls)),
)
accounts/urls.py.
from
django.conf.urls
import
patterns
,
url
urlpatterns
=
patterns
(
''
,
Mocking in Python
|
279