Source URL: https://stackoverflow.com/questions/76531474/django-ninja-testing
Django Ninja Testing
Asked 1 year, 1 month ago
Modified 4 months ago
Viewed 2k times
4
I am trying to create a test for an API I wrote using Django-Ninja.
Here is my model:
class Country(models.Model):
created_at = models.DateTimeField(auto_created=True, auto_now_add=True)
name = models.CharField(max_length=128, null=False, blank=False)
code = models.CharField(max_length=128, null=False, blank=False, unique=True)
timezone = models.CharField(max_length=128, null=False, blank=False)
Here is my schema:
class CountryAddSchema(Schema):
name: str
code: str
timezone: str
Here is the endpoint of the post:
router.post("/add",
description="Add a Country",
summary="Add a Country", tags=["Address"],
response={201: DefaultSchema, 401: DefaultSchema, 422: DefaultSchema, 500: DefaultSchema},
url_name="address_country_add")
def country_add(request, country: CountryAddSchema):
try:
if not request.auth.belongs_to.is_staff:
return 401, {"detail": "None Staff cannot add Country"}
the_country = Country.objects.create(**country.dict())
the_country.save()
return 201, {"detail": "New Country created"}
except Exception as e:
return 500, {"detail": str(e)}
Finally, here is the test function:
def test_add_correct(self):
"""
Add a country
"""
data = {
"name": "".join(choices(ascii_letters, k=32)),
"code": "".join(choices(ascii_letters, k=32)),
"timezone": "".join(choices(ascii_letters, k=32))
}
respond = self.client.post(reverse("api-1.0.0:address_country_add"), data, **self.AUTHORIZED_HEADER)
self.assertEquals(respond.status_code, 201)
self.assertDictEqual(json.loads(respond.content), {"detail": "New Country created"})
the_country = Country.objects.last()
self.assertDictEqual(
data,
{
"name": the_country.name,
"code": the_country.code,
"timezone": the_country.timezone
}
)
Note that I set self.AUTHORIZED_HEADER in setUp.
And here is the error:
FAIL: test_add_correct (address.tests_country.CountryTest)
Add a country
----------------------------------------------------------------------
Traceback (most recent call last):
File "SOME_PATH/tests_country.py", line 80, in test_add_correct
self.assertEquals(respond.status_code, 201)
AssertionError: 400 != 201
I can add a country using the Swagger provided by Django-Ninja. I mean the endpoint works. But I cannot test it using djano.test.Client.
Any Idea?
Update:
Here is the curl code generated by swagger:
curl -X 'POST' \
'http://127.0.0.1:8000/api/address/country/add' \
-H 'accept: application/json' \
-H 'X-API-Key: API-KEY' \
-H 'Content-Type: application/json' \
-d '{
"name": "string",
"code": "string",
"timezone": "string"
}'
3 Answers 3
Sort by: Reset to default
Highest score (default) Trending (recent votes count more) Date modified (newest first) Date created (oldest first)
4
I had an error {"detail": "Cannot parse request body"} .
It turns out that Django-ninja expects the data to be passed as JSON, but by default the test client sets content_type to multipart/form-data; boundary=BoUnDaRyStRiNg. When you explicitly specify that the content type should be JSON, it will work.
Client().post(url, {"your": "dict"}, content_type="application/json")
Note: Setting the content type in the headers will not work because it will be overridden.
Follow
Answered Nov 15, 2023 at 8:22
Jorrick SleijsterJorrick Sleijster
109711 gold badges1212 silver badges2626 bronze badges
2
Try converting it to JSON:
self.client.post(
reverse("api-1.0.0:address_country_add"),
json.dumps(data),
content_type="application/json",
**self.AUTHORIZED_HEADER
)
Follow
Answered Jul 10, 2023 at 7:26
DjangonautDjangonaut
5,77177 gold badges4141 silver badges5555 bronze badges
2
- I have tried it. I found a solution. I used
urllib.parse.urlencode. I will post the answer as soon as possible.
– MSH
Commented Jul 10, 2023 at 20:32
- Hi, could you please post your answer? I am running into a similar issue
Commented Nov 15, 2023 at 8:12
1
When sending data with the Django test client, make sure to send it as JSON data since your endpoint expects JSON:
def test_add_correct(self):
"""
Add country
"""
data = {
"name": "".join(choices(ascii_letters, k=32)),
"code": "".join(choices(ascii_letters, k=32)),
"timezone": "".join(choices(ascii_letters, k=32))
}
# Convert data to JSON format
data_json = json.dumps(data)
# Send the request with JSON data
respond = self.client.post(reverse("api-1.0.0:address_country_add"), data=data_json, content_type='application/json', **self.AUTHORIZED_HEADER)
# Rest of your test code_____
This should match your API endpoint's expectations and resolve the 400 status code issue.
Follow
Answered Mar 18 at 5:11
Nayem Jaman Tusher
97122 gold badges88 silver badges2222 bronze badges
本文总阅读量次

