Есть ли правильный способ заставить мальчика-фабриканта подключиться к тестовой базе данных?
У меня возникает очень раздражающая ошибка в тестовых наборах моего проекта, потому что factory boy запускает каждый тестовый пример на основной/дефолтной базе данных, вместо того чтобы запускать запросы на соответствующей тестовой базе данных.
Я попробовал добавить конфигурацию класса Meta в фабричный класс (как рекомендовано в этом посте), но как только я пытаюсь запустить набор тестов django, приложение выдает ошибку, утверждая, что соединение с тестовой базой данных не существует.
Буду очень признателен за любую помощь, поскольку документация совершенно не проясняет эту ситуацию.
Мой settings.py:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": 'DB_NAME',
"USER": 'DB_USER',
"PASSWORD": 'DB_PSSWD',
"HOST": 'DB_HOST',
"PORT": 3306,
"TEST":{
"NAME": 'TEST_DB_NAME',
},
"OPTIONS": {
"init_command": "SET sql_mode='STRICT_TRANS_TABLES'; SET foreign_key_checks = 0;",
},
}
}
my factory.py:
import factory
class CustomModelFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.CustomModel
database = 'TEST_DB_NAME'
django_get_or_create = ('nu_cnpj',)
nm_razao_social = factory.Faker(locale='pt_BR', provider='company')
nu_cnpj = factory.Faker(locale='pt_BR', provider='company_id')
my model.py:
from django.db import models
class CustomModel(models.Model):
nu_cnpj = models.CharField(unique=True, max_length=20, blank=True, null=True)
nm_razao_social = models.CharField(max_length=255, blank=False, null=False)
Ошибка:
python manage.py test flux.tests.test_data_leak_main_db --keepdb
Traceback (most recent call last):
File "C:\Users\project\venv\lib\site-packages\django\db\utils.py", line 172, in ensure_defaults
conn = self.databases[alias]
KeyError: 'TEST_DB_NAME'
During handling of the above exception, another exception occurred:
...
raise ConnectionDoesNotExist("The connection %s doesn't exist" % alias)
django.db.utils.ConnectionDoesNotExist: The connection TEST_DB_NAME doesn't exist
В конце концов, я и мои коллеги по команде смогли отследить, какая именно реализация фабрики генерировала это странное поведение.Был вызов фабрики внутри определения класса фабрики, что привело к вставке данных во время фазы импорта (которая предшествовала созданию тестовой базы данных из базы данных по умолчанию). Поэтому объекты фабрик вставлялись в базу данных по умолчанию, которая была единственной доступной для ORM.
Ошибочная реализация выглядела следующим образом:
import factory
class CustomModelFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.CustomModel
database = 'TEST_DB_NAME'
django_get_or_create = ('nu_cnpj',)
nm_razao_social = factory.Faker(locale='pt_BR', provider='company')
nu_cnpj = factory.Faker(locale='pt_BR', provider='company_id')
class Params:
test = factory.Trait(
nm_razao_social='Test',
)
class ForeignRelatedCustomModelFactory(factory.django.DjangoModelFactory):
name = factory.Faker(locale='pt_BR', provider='first_name')
address = factory.Faker('address')
status = factory.Faker('pystr')
fk = factory.SubFactory('CustomModelFactory')
class Params:
test = factory.Trait(
fk=CustomModelFactory(test=True), # this line resulted in a factory call during import, inserting data into the 'default' database instead of the test replica db, during the execution of `python manage.py test`
name='Test'
)