Search code examples
pythondjangopytestdjango-sessions

Data saved in session in a view is not saved in pytest session. Why?


I am making a website with Django and would like to test the data stored in session with pytest.

I have a very simple view :

def dev_my_view(request):
    if request.method == "POST":
        post_data = json.loads(request.body.decode("utf-8"))
        product_id = post_data["productid"]
        request.session["basket"] = {"id": product_id}

        # print(request.session.items()) returns 
        # dict_items([('foo', 'bar'), ('basket', {'id, '99'})])
        # as expected

        response = JsonResponse({"id": f"product number {product_id}"})
        return response

Here is the test I have written :

class TestViewsWithSession(TestCase):
    def test_my_view(self):
        session = self.client.session
        session["foo"] = "bar"
        session.save()
        url = reverse("home_page:my_view")
        response = self.client.post(
            url,
            json.dumps({"productid": "99"}),
            content_type="application/json",
        )

        # print(session.items()) returns 
        # dict_items([('foo', 'bar')])
               
        # Test passes
        self.assertEqual(response.status_code, 200)

        # Test passes
        # response.content = b'{"id": "product number 99"}
        self.assertJSONEqual(response.content, {"id": "product number 99"})

        # Test fails. KeyError: 'basket'
        self.assertEqual(
            session["basket"],
            {"id": "99"},
        )
        self.assertNotEqual(
            session["basket"],
            {"id": "Invalid value"},
        )

When I add data to the session in the test (session["foo"] = "bar"), the session contains this data in the view.

But, it looks it does not work the other way ...

When some data is added to the session in the view (request.session["basket"] = {"id": product_id}), I cannot see this data in the test. Why ?


Solution

  • The test client uses a different session engine than the one used in the view. The session data stored in the view is not 'transfered' to the test.

    But it is possible to access the session data directly from the request object like this:

    def test_my_view(self):
        session = self.client.session
        session["foo"] = "bar"
        session.save()
        url = reverse("home_page:my_view")
        response = self.client.post(
            url,
            json.dumps({"productid": "99"}),
            content_type="application/json",
        )
    
        request = response.wsgi_request
        self.assertEqual(
            request.session["basket"],
            {"id": "99"},
        )