Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate a fake HTTP request object for unit test in Python?

In a Python Django project, we want a unit test to feed a HTTP POST request into the function under test. The cURL sample command below shows our test settings.

The cURL approach starts from the web server's endpoint and triggers the entire logic path, but we want the unit test to focus on a specific function taking in the request argument. And, we got hint from this post with the below sample Python source code to fake a HTTP request for testing.

Our Question:

See the -d argument of the cURL command, we wonder how to feed the request body in the faked object.

Technical Details:

  • The cURL command:
curl http://127.0.0.1:8000/api/transaction/ --insecure \
    --verbose \
    -d '<env:Envelope ... >
  <env:Header>
    ...
  </env:Header>
  <env:Body>
    ...
  </env:Body>
</env:Envelope>
'
  • The Python sample source code for faking a HTTP request:
from django.core.handlers.wsgi import WSGIRequest
from io import StringIO
from django.contrib.auth.models import AnonymousUser

def GetFakeRequest(path='/', user=None):
    """ Construct a fake request(WSGIRequest) object"""
    req = WSGIRequest({
        'REQUEST_METHOD': 'GET',
        'PATH_INFO': path,
        'wsgi.input': StringIO()})

    req.user = AnonymousUser() if user is None else user
    return req
like image 794
James Avatar asked Jan 17 '26 18:01

James


1 Answers

Maybe an alternative is to build the request object using RequestFactory. And call the the function using such as param. Something like:

tests.py

from django.test import TestCase, RequestFactory
from django.contrib.auth import get_user_model

from myapp.views import my_function


class TestHTTPRequest(TestCase):
    def setUp(self) -> None:
        self.data = "<env:Envelope ... > \
                        <env:Header> \
                            ... \
                        </env:Header> \
                        <env:Body> \
                            ... \
                        </env:Body> \
                    </env:Envelope>"
        self.factory = RequestFactory()
        self.user = get_user_model().objects.create_user(
            username="john", email="[email protected]", password="top_secret"
        )

    def test_some_function(self):
        request = self.factory.get("some/url/", data={'data': self.data})
        request.user = self.user

        response = my_function(request)

        self.assertEqual(response, "Some way to confirm success")

views.py

def my_function(request):
    data = request.GET.get('data')
    # print(f'The data: \n {data}')
    
    # print(request.user.email)

    return "Some way to confirm success"

I placed it inside views, but of course it can be anywhere you want.

like image 147
Niko Avatar answered Jan 19 '26 07:01

Niko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!