How to mock users and requests in django
Question:
I have django code that interacts with request objects or user objects. For instance something like:
foo_model_instance = models.get_or_create_foo_from_user(request.user)
If you were going to test with the django python shell or in a unittest, what would you pass in there? Here simply a User object will do, but the need for a mock request object also comes up frequently.
For the shell or for unittests:
- How do you mock users?
- How do you mock requests?
Answers:
Read about mock objects here
http://en.wikipedia.org/wiki/Mock_object
http://www.mockobjects.com/
And use this python lib to mock a user
http://python-mock.sourceforge.net/
else you can write a simple User class yourself, use this as a starting point
class MockUser(object):
def __call__(self, *args, **kwargs):
return self
def __getattr__(Self, name):
return self
add specfic cases etc etc
How do you mock users?
Initialise a django.contrib.auth.models.User
object. User.objects.create_user
makes this easy.
How do you mock requests?
Initialise a django.http.HttpRequest
object.
Of course, there are shortcuts depending on what you want to do. If you just need an object with a user
attribute that points to a user, simply create something (anything) and give it that attribute.
You don’t need to mock Users, as you can just create one within your test – the database is destroyed after the test is finished.
To mock requests, use this snippet from Simon Willison.
You can either roll your own mocks, as Anurag Uniyal has suggested, or you can use a mocking framework.
In response to those saying you can just create an ordinary user as you would anyway in Django… I would suggest this defeats the point of the unit test. A unit test shouldn’t touch the database, but by creating a user, you’ve changed the database, hence why we would want to mock one.
For request, I would use RequestFactory included with Django.
from django.test.client import RequestFactory
rf = RequestFactory()
get_request = rf.get('/hello/')
post_request = rf.post('/submit/', {'foo': 'bar'})
for users, I would use django.contrib.auth.models.User as @ozan suggested and maybe with factory boy for speed (with factory boy you can choose to not to save to DB)
There are already a lot of good general answers. Here is a simple mock user used in tests involving admin forms:
class MockUser:
is_active = True
is_staff = True
def has_perm(self, *args):
return True
from django.test.client import RequestFactory
request = RequestFactory().get("/some/url")
request.user = MockUser()
I have django code that interacts with request objects or user objects. For instance something like:
foo_model_instance = models.get_or_create_foo_from_user(request.user)
If you were going to test with the django python shell or in a unittest, what would you pass in there? Here simply a User object will do, but the need for a mock request object also comes up frequently.
For the shell or for unittests:
- How do you mock users?
- How do you mock requests?
Read about mock objects here
http://en.wikipedia.org/wiki/Mock_object
http://www.mockobjects.com/
And use this python lib to mock a user
http://python-mock.sourceforge.net/
else you can write a simple User class yourself, use this as a starting point
class MockUser(object):
def __call__(self, *args, **kwargs):
return self
def __getattr__(Self, name):
return self
add specfic cases etc etc
How do you mock users?
Initialise a django.contrib.auth.models.User
object. User.objects.create_user
makes this easy.
How do you mock requests?
Initialise a django.http.HttpRequest
object.
Of course, there are shortcuts depending on what you want to do. If you just need an object with a user
attribute that points to a user, simply create something (anything) and give it that attribute.
You don’t need to mock Users, as you can just create one within your test – the database is destroyed after the test is finished.
To mock requests, use this snippet from Simon Willison.
You can either roll your own mocks, as Anurag Uniyal has suggested, or you can use a mocking framework.
In response to those saying you can just create an ordinary user as you would anyway in Django… I would suggest this defeats the point of the unit test. A unit test shouldn’t touch the database, but by creating a user, you’ve changed the database, hence why we would want to mock one.
For request, I would use RequestFactory included with Django.
from django.test.client import RequestFactory
rf = RequestFactory()
get_request = rf.get('/hello/')
post_request = rf.post('/submit/', {'foo': 'bar'})
for users, I would use django.contrib.auth.models.User as @ozan suggested and maybe with factory boy for speed (with factory boy you can choose to not to save to DB)
There are already a lot of good general answers. Here is a simple mock user used in tests involving admin forms:
class MockUser:
is_active = True
is_staff = True
def has_perm(self, *args):
return True
from django.test.client import RequestFactory
request = RequestFactory().get("/some/url")
request.user = MockUser()