I am writing a Django test inheriting from django.test.TestCase. Everywhere, in the docs, this tutorial and even in this accepted SO accepted answer is stated that when using Django TestCase, a test db will be automatically created.
Previously I have worked with DRF APITestCases and all worked well. Here I am using the very standard approach but the setUpTestData class method is using my production db.
What do I do wrong and what has to be done so a test db is spawned and used for the test? Please see my code bellow.
from django.test import TestCase
from agregator.models import AgregatorProduct
from django.db.models import signals
def sample_product_one():
sample_product_one = {
# "id": 1,
"name": "testProdOne",
"dph": 21,
"updated": datetime.now(),
"active": True,
"updatedinstore": False,
"imagechanged": False,
"isVirtualProduct": False,
}
return sample_product_one
class TestCreateProdToCategory(TestCase):
"""
Test for correct creation of records
"""
@classmethod
@factory.django.mute_signals(signals.pre_save, signals.post_save)
def setUpTestData(cls):
AgregatorProduct.objects.create(
**sample_product_one()
)
def test_create_prod_to_cat(self):
product = AgregatorProduct.objects.get(id=1)
self.assertEqual(product.id, 1)
DB set up:
DATABASES = {
'agregator': {
'NAME': 'name',
'ENGINE': 'sql_server.pyodbc',
'HOST': 'my_ip',
'USER': 'my_user',
'PASSWORD': 'my_pwd',
'OPTIONS': {
'driver': 'ODBC Driver 17 for SQL Server',
'isolation_level': 'READ UNCOMMITTED',
},
}
}
The test results in
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\xevos\xevosadmin\agregator\tests\test_admin_actions\test_products_to_categories_admin_action.py", line 64, in test_create_prod_to_cat
product = AgregatorProduct.objects.get(id=1)
File "C:\xevos\xevosadmin\.venv\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\xevos\xevosadmin\.venv\lib\site-packages\django\db\models\query.py", line 397, in get
raise self.model.DoesNotExist(
agregator.models.AgregatorProduct.DoesNotExist: AgregatorProduct matching query does not exist.
----------------------------------------------------------------------
which is a result of id being autoincrementing and given there are products in the production db already, it gets id of eg 151545
(AgregatorProduct matching query does not exist. is a result of the fact that the product which used to have id=1 was deleted a long time ago in the production db.)
So the test writes to the existing database and the data persist there even after the test is finished.
1 Answer 1
To create a test database, use the setUp method inside TestCase and run it using python manage.py test
from django.test import TestCase
from myapp.models import Animal
class AnimalTestCase(TestCase):
def setUp(self):
Animal.objects.create(name="lion", sound="roar")
Animal.objects.create(name="cat", sound="meow")
def test_animals_can_speak(self):
"""Animals that can speak are correctly identified"""
lion = Animal.objects.get(name="lion")
cat = Animal.objects.get(name="cat")
self.assertEqual(lion.speak(), 'The lion says "roar"')
self.assertEqual(cat.speak(), 'The cat says "meow"')
The database will be created and deleted automatically after tests are done https://docs.djangoproject.com/en/3.1/topics/testing/overview/#writing-tests
1 Comment
setUp method does the same as setUpTestData method except for that setUpTestData runs only once to set up the scene, not for each subtest so results in the same errorExplore related questions
See similar questions with these tags.
./manage.py test, additional care may be needed for all the test preparation in Django to work properly