Макет атрибута по умолчанию SQLAlchemy - PullRequest
0 голосов
/ 18 января 2019

У меня есть некоторые проблемы с макетом объекта SQLAlchemy при использовании полей default и onupdate в моих моделях:

def get_uuid():
    return str(uuid.uuid4())

def get_now():
    return db.func.now()

class BaseModel(db.Model):
    __abstract__ = True

    id = db.Column(UUIDType(binary=False), primary_key=True, nullable=False, default=get_uuid)
    created_at = db.Column(db.DateTime(timezone=True), default=get_now(), nullable=False, index=True)

Поведение get_now() и get_uuid() не меняется, даже когда я пытаюсь имитировать их в своих тестах:

def test_create_source(client, mocker):

    mock = mocker.MagicMock(return_value='123e4567-e89b-12d3-a456-426655440000')
    mocker.patch('myproject.models.get_uuid', mock)
    mock = mocker.MagicMock(return_value=datetime.datetime(2019, 1, 1))
    mocker.patch('myproject.models.get_now', mock)

    resp = client.post('/sources', json={'name': 'My source'})
    assert resp.json == {
        'name': 'My source',
        'id': '123e4567-e89b-12d3-a456-426655440000',
        'createdAt': 'Tue, 01 Jan 2019 00:00:00 GMT',
        'updatedAt': 'Tue, 01 Jan 2019 00:00:00 GMT'
    }

### Results :

>       assert resp.json == {
            'name': 'My source',
            'id': '123e4567-e89b-12d3-a456-426655440000',
            'createdAt': 'Tue, 01 Jan 2019 00:00:00 GMT',
            'updatedAt': 'Tue, 01 Jan 2019 00:00:00 GMT'
        }
E       AssertionError: assert {'createdAt':...17:38:38 GMT'} == {'createdAt': ...00:00:00 GMT'}
E         Omitting 1 identical items, use -vv to show
E         Differing items:
E         {'id': '8eb074c0-41e9-436c-8f71-b4c6842f4809'} != {'id': '123e4567-e89b-12d3-a456-426655440000'}
E         {'createdAt': 'Fri, 18 Jan 2019 17:38:38 GMT'} != {'createdAt': 'Tue, 01 Jan 2019 00:00:00 GMT'}
E         {'updatedAt': 'Fri, 18 Jan 2019 17:38:38 GMT'} != {'updatedAt': 'Tue, 01 Jan 2019 00:00:00 GMT'}
E         Use -v to get the full diff

tests/test_sources.py:17: AssertionError

Я думаю, это потому, что мои модели и их атрибуты уже импортированы и оценены перед выполнением моего теста, поэтому макет здесь бесполезен. Это объясняется в части «1010 * сообщение », но я все еще не смог решить мою проблему: (

Полный исполняемый код для воспроизведения проблемы доступен здесь: https://github.com/ncrocfer/flaskmock

У вас есть идеи, пожалуйста?

1 Ответ

0 голосов
/ 19 января 2019

Я думаю, это потому, что мои модели и их атрибуты уже импортированы и оценены перед выполнением моего теста, поэтому макет здесь бесполезен.

Закрыть: вы передали ссылку на функцию get_uuid() по умолчанию на id и результат вызова get_now() (объект выражения функции) по умолчанию на created_at. Изменение того, с чем связаны эти имена в модуле после того, как факт больше не влияет на столбцы, которые уже содержат ссылки на сами объекты.

В случае get_uuid() вы должны смоделировать вызываемую функцию:

mock = mocker.MagicMock(return_value='123e4567-e89b-12d3-a456-426655440000')
mocker.patch('uuid.uuid4', mock)

, а в случае get_now() не стоит вызывать его при построении модели:

class BaseModel(db.Model):
    ...
    created_at = db.Column(..., default=get_now, ...)

так что вы снова можете высмеивать реальную функцию, которую она вызывает:

mock = mocker.MagicMock(return_value=datetime.datetime(2019, 1, 1))
mocker.patch('sqlalchemy.func.now', mock)

С другой стороны, возможно, вам не следует ничего утверждать о id и временных метках в тесте, поскольку, похоже, важно убедиться, что имя задано правильно.

...