pythondjangounit-testingdjango-rest-frameworkpytest-django

Getting a 404 error when sending a POST request with APIClient in Django test case


I'm writing a test case for a Django REST Framework API using the APIClient from the rest_framework.test module. I'm trying to send a POST request to the wordOftheDay/ endpoint with the provided data, but I keep getting a 404 error. It seems that the code in the except block is being executed directly when I run it using unit test command, without entering the try block at all. Interestingly, when I manually make the API call using Postman, I receive a 200 OK response.

def test_valid_post_request(self):
        client = APIClient()
        print(client)
        response = client.post('wordOftheDay/', self.valid_data, format='json')
        print('response',response)
        self.assertEqual(response.status_code, 200)
        print('response.status_code',response.status_code)
        # Check if the model is created with the expected data
        self.assertTrue(WordModel.objects.filter(device_id=self.valid_data['device_id']).exists())

Update - Adding the API call code here for reference.

def post(self, request, **kwargs):
        #d_param = request.query_params.get('d')
        d_type = request.data.get('d_type')
        o_version = request.data.get('o_version')
        d_id = request.data.get('d_id')
        w_family = request.data.get('w_family')

        if device_type is not None and os_version is not None and device_id is not None and widget_family is not None:
            device_analytics = {
                'd_type' : d_type,
                'o_version' : o_version,
                'd_id' : d_id,
                'w_family' : w_family,
            }

            self.updateDA(device_analytics, d_id, w_family)

            try:
                # #current_date = date.today()
                # current_date = '2023-10-21'
                # date_string = str(current_date)
                # valid_date = datetime.strptime(date_string, '%Y-%m-%d').date()
                #
                # if valid_date:
                #
                #     word_instance = WordModel.objects.get(date=valid_date)
                #     serializer = WordSerializers(word_instance)

                word_instance = WordModel.objects.get(id=43)
                serializer = WordSerializers(word_instance)

                return Response(serializer.data, status=status.HTTP_200_OK)

            except WordModel.DoesNotExist:
                return Response({"error": "Data for the given date does not exist"}, status=status.HTTP_404_NOT_FOUND)

I have commented the original logic of the try block for reference and replaced it with a logic to return a specific record for simplicity.However, I am still receiving a 404 error with a response ("error":"Data for the given date does not exist") - when I run it through this command - python manage.py test wordOfTheDay.tests.test_wordOfTheDay. Interestingly, when I manually make the API call using Postman, I receive a 200 OK response.


Solution

  • So, I think you are missing important thing about tests, when django runs tests it creates new database, not relied to your main one, and no data form your original app will be accessible in test, so there is no object with id = 43 in there, until you create it. Basic strategy for tests is first to run tests that create some data with POST requests, and then check if data was saved properly with GET requests.

    More about db: https://docs.djangoproject.com/en/4.2/topics/testing/overview/#the-test-database