Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django test client does not automatically serialize factories

Here's my code:

# models.py
class MyModel(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=10)
    ...

# views.py
def get_all_models(request):
    return JsonResponse({"models": list(MyModel.objects.all())})

# urls.py
path('/mypath', views.get_all_models, name='get_all_models'),

This code works just fine if I visit /mypath. However, when I run an automated test using Django's test client, I get this error:

*** TypeError: Object of type MyModel is not JSON serializable

this is my test: from django.test import TestCase, Client from blog.tests.factories.user import UserFactory from blog.tests.factories.post import PostFactory

class MyModelTest(TestCase):
    def setUp(self):
        self.user = UserFactory.create()
        self.post = MyModelFactory.create(user=self.user)
        self.client = Client()

    def test_get_all_models(self):
        response = self.client.get("/mypath")
        pass

I suspect it has something to do with my factories:

import factory
from .models import User, MyModel

class UserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = User

    username = factory.Faker('word')
    email = factory.Faker('email')

class MyModelFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = MyModel

    user = factory.SubFactory(UserFactory)
    name = factory.Faker('name')

How can I make my factories serializable?

NOTE: This question is not a duplicate. The other questions linked have view handlers that return HttpResponse objects, instead of JsonResponse objects. This distinction is key to my problem, because the error I'm seeing is related to JSON serialization that is supposed to be addressed by the JsonResponse class.

Also, the other questions do not involve factories. Factories are another key component of what I'm trying to do, which is run integration tests against data generated by factories.

like image 697
dopatraman Avatar asked Apr 24 '19 05:04

dopatraman


People also ask

What is serializing and Deserializing in Django?

Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.

What is DjangoModelFactory?

DjangoModelFactory is a basic interface from factory_boy that gives "ORM powers" to your factories. It's main feature here is that it provides you with a common "create" and "build" strategies that you can use to generate objects in your tests.

How does serialization work in Django?

Django's serialization framework provides a mechanism for “translating” Django models into other formats. Usually these other formats will be text-based and used for sending Django data over a wire, but it's possible for a serializer to handle any format (text-based or not).

Where does Django store test database?

from the docs: When using SQLite, the tests will use an in-memory database by default (i.e., the database will be created in memory, bypassing the filesystem entirely!). The TEST dictionary in DATABASES offers a number of settings to configure your test database.


1 Answers

The code you shared assumes JSONResponse will serialize an ORM object, but according to Django documentation, it won't:

https://docs.djangoproject.com/en/3.0/ref/request-response/#jsonresponse-objects

https://docs.djangoproject.com/en/3.0/topics/serialization/#djangojsonencoder

It will work if you serialize the Django ORM object before passing it to JSONResponse

Consider doing the following:

from django.core import serializers
data = serializers.serialize("json", MyModel.objects.all())

https://docs.djangoproject.com/en/3.0/topics/serialization/

django-rest-framework is a very popular lib used in scenarios like the one you shared https://docs.djangoproject.com/en/3.0/topics/serialization/#djangojsonencoder

like image 124
Márcio Carôso Avatar answered Oct 26 '22 15:10

Márcio Carôso