Django unit tests - запрос содержимого тестовой базы данных - PullRequest
0 голосов
/ 05 мая 2020

Может ли кто-нибудь указать мне на ресурс, который показывает, как запросить Django тестовую таблицу c базы данных во время модульного теста?

У меня есть следующий тестовый код:

from django.test import TestCase
from users.models import User

class DisputeAssignerTestSuite(TestCase):

    databases = [
        'default', 
        'read_replica',
        ]

    @classmethod
    def setUpTestData(cls):
        cls.users = UserFactory.create_batch(50)

    def test_firstOne(self):
        print(users)
        print(User.objects.all())

Код UserFactory:

import factory
from faker import Factory
import pytz

from users.models import User

faker = Factory.create()

class UserFactory(factory.DjangoModelFactory):
    class Meta:
        model = User
        django_get_or_create = ('first_name', 'last_name', 'timezone', 'locale')

    first_name = factory.LazyAttribute(lambda _: faker.first_name())
    last_name = factory.LazyAttribute(lambda _: faker.last_name())
    display_name = factory.LazyAttribute(lambda _: _.first_name + " " + _.last_name)    
    timezone = factory.LazyAttribute(lambda _: faker.timezone())
    locale = factory.LazyAttribute(lambda _: faker.random_choices(elements=('en-au', 'en-us', 'de-de', 'fr-fr'), length=1))
    password = factory.LazyAttribute(lambda _: faker.password(length=12))
    last_login = factory.LazyAttribute(lambda _: faker.past_datetime(start_date="-60d", tzinfo=pytz.timezone(faker.timezone())))
    is_superuser = factory.LazyAttribute(lambda _: faker.boolean(50))
    email = factory.LazyAttribute(lambda _: faker.email())
    username = factory.LazyAttribute(lambda _: _.email)
    is_staff = factory.LazyAttribute(lambda _: faker.boolean(50))
    is_active = factory.LazyAttribute(lambda _: faker.boolean(50))
    date_joined = factory.LazyAttribute(lambda _: faker.past_datetime(start_date="-1y", tzinfo=pytz.timezone(faker.timezone())))

Я не понимаю, как я могу запросить таблицу User в тестовой базе данных, созданной Django для этого запуска TestCase, и, например, проверить ее содержимое на некоторые конкретные c требование (например, наличие пользователей по указанному c имени и т. Д. c.).

Когда я пишу:

print(User.objects.all())

, я получаю вывод производственной БД .

Помогите!

ОБНОВЛЕНИЕ:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': global_config['postgresql']['database'],
        'USER': global_config['postgresql']['user'],
        'PASSWORD': global_config.get('postgresql', 'password'),
        'HOST': global_config['postgresql']['host'],
        'PORT': global_config['postgresql']['port'],
        'CONN_MAX_AGE': 30,
        'TEST': {
            'NAME': 'mytestdatabase',
        },
        'OPTIONS': {
            'connect_timeout': 60,
            'sslmode': 'prefer'
        },
    },
    'read_replica': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': global_config['postgresql']['database_read_replica'],
        'USER': global_config['postgresql']['user_read_replica'],
        'PASSWORD': global_config.get('postgresql', 'password_read_replica'),
        'HOST': global_config['postgresql']['host_read_replica'],
        'PORT': global_config['postgresql']['port_read_replica'],
        'CONN_MAX_AGE': 30,
        'TEST': {
            'MIRROR': 'default',
        },
        'OPTIONS': {
            'connect_timeout': 60,
            'sslmode': 'prefer'
        },
    }

REPLICA_DATABASES = ['read_replica',]
DATABASE_ROUTERS = [
    'multidb.PinningReplicaRouter',
    ]

1 Ответ

0 голосов
/ 11 мая 2020

Что ж, после того, как я ОЧЕНЬ повозился с этой проблемой, я наконец обнаружил, что источником проблемы было промежуточное ПО multidb.PinningReplicaRouter для маршрутизации базы данных. При использовании в Django 2.2.11 и Python 3.7 в моем случае это препятствовало правильной маршрутизации запросов к тестовой базе данных и вместо этого нарушало уровень изоляции PROD / DEV, записывая в ??? (трудно сказать, так как я не мог выполнить обратное чтение) и чтение из базы данных PROD.

Я решил проблему, включив следующий декоратор перед тестовыми наборами, которые я хотел запустить:

@modify_settings(DATABASE_ROUTERS={'remove': 'multidb.PinningReplicaRouter'})
class SomeTestSuite(TestCase):
    # some test logic

Надеюсь, это принесет пользу кому-то в будущем.

...