Reputation: 416
My Django tests all pass when I use the built-in SQLite as my database. However, when I switch to the built-in MySQL and PostgreSQL, they fail. (All local database servers.)
The connections to the DB are live enough -- the database is created and migrations applied. But the tests aren't even hitting views.py
before the test server returns a 500 (and no additional explanation beyond "Server Error", even in debug mode).
I'm using Django with Django REST Framework, and testing with REST Framework's RequestsClient
class. My test fixtures are generated with Factory Boy.
Any ideas? I have a vague feeling it's to do with Factory Boy but nothing concrete. The fact that it fails with multiple databases, and successfully builds the tables, makes me suspect it's not the database itself.
Versions tested:
Upvotes: 2
Views: 921
Reputation: 666
I don't have the exact answer to this question, but I had a similar problem where PostgreSQL complained about not finding a Foreign Key that has the id=1
. This happened because -in some tests- I have hardcoded the object to test on to be the one having id=1
. This worked fine on SQLite because the IDs were given sequentially starting from 1, however, this is not happening on PostgreSQL. I solved it by using the Model.objects.last().pk
or Model.objects.first().pk
or choosing another instance in between when I need to use a Primary Key.
Upvotes: 0
Reputation: 370
I had a similar problem (not sure if its the same) going from SQLite to PostgreSQL. Are you using a setup method to setup your initial database objects?
Example::
def setUp(self):
user = User.objects.create_user(username='john', password='abbeyRd', email='[email protected]')
user.save()
I found that this would work fine on SQLite, but on PostgreSQL I was getting database connection failures (it would still build the database like you said, but couldn't run the tests without a connection error).
Turns out, the fix is to run your setup method as follows:
@classmethod
def setUpTestData(cls):
user = User.objects.create_user(username='john', password='abbeyRd', email='[email protected]')
user.save()
I don't remember the exact reason why this works and the other one didn't, but it had something to do with the connection to the database trying to reconnect every test if you use setUp(self)
and if you use setUpTestData(cls)
it only connects when the class is instantiated, but I might not have the details perfect. All I really know is it works!
Hope that helps, not sure if it addresses your exact issue, but it took me a good few hours to figure out, so I hope it helps you and maybe others in the future!
Upvotes: 1
Reputation: 416
It turned out to be because of the testing class I was using. Apparently, although it is not right now stated in the documentation, the Django REST Framework RequestsClient
class can only be used with the DRF APILiveServerTestCase
. That is worked at all with SQLite is a weird fluke.
Link: https://github.com/encode/django-rest-framework/issues/5801
Edited to add, here's the reason for the "weird fluke", per the Django documentation:
When using an in-memory SQLite database to run the tests, the same database connection will be shared by two threads in parallel: the thread in which the live server is run and the thread in which the test case is run.
Upvotes: 0