How to mock users and requests in django

PythonDjangoUnit TestingMocking

Python Problem Overview


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?

Python Solutions


Solution 1 - Python

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)

Solution 2 - Python

> 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.

Solution 3 - Python

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.

Solution 4 - Python

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

Solution 5 - Python

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPurrellView Question on Stackoverflow
Solution 1 - PythonnaokoView Answer on Stackoverflow
Solution 2 - PythonozanView Answer on Stackoverflow
Solution 3 - PythonMichael WilliamsonView Answer on Stackoverflow
Solution 4 - PythonAnurag UniyalView Answer on Stackoverflow
Solution 5 - PythonDaniel RosemanView Answer on Stackoverflow