Найти - Пользователи
Полная версия: Как при помощи mock и SQLAlchemy изменить дату при автосохранении объекта в базу данных?
Начало » Базы данных » Как при помощи mock и SQLAlchemy изменить дату при автосохранении объекта в базу данных?
1
qnica
Добрый день. Использую Flask + SQLAlchemy.
Имеется модель такого типа:
class Entry(db.Model):
    __tablename__ = 'entries'
    name = db.Column(db.String(100))
    created = db.Column(db.DateTime(), default=datetime.now)
    updated = db.Column(db.DateTime(), default=datetime.now, onupdate=datetime.now)

Как подменить время создания и обновления? К примеру для такого теста:
class ViewTestCase(AppliactionTestCase):
    def test(self):
        with freeze_time("2014-06-01 16:00:00"):
            db.session.add(Entry(name="title"))
            db.session.commit()
        entry = db.session.query(Entry).first()
        self.assertEqual(entry.created, datetime(2014, 6, 1, 16, 0, 0))
        self.assertEqual(entry.updated, datetime(2014, 6, 1, 16, 0, 0))
        with freeze_time("2014-07-01 17:00:00"):
            entry.name = 'edited title'
            db.session.add(entry)
            db.session.commit()
       entry = db.session.query(Entry).first()
       self.assertEqual(entry.created, datetime(2014, 6, 1, 16, 0, 0))
       self.assertEqual(entry.updated, datetime(2014, 7, 1, 17, 0, 0))

Для подмены времения я использую freezegun. Но с ходу он не подменяет.
Я также пытался с помощью mock патчить db.DateTime.python_type, что бы он возвращал FakeDatetime, но результат тот же.

Я обратил внимание что если определять поля так:
created = db.Column(db.DateTime(), default=lambda: datetime.now())
То все работает. Но переписывать все под тесты не охота, да и неправильно это.

Подскажите, если кто сталкивался с этим, или знает где нужно подменить метод, отзовитесь, пожалуйста.
4kpt_III
Что Вы тестируете? Я, если честно, понять не могу
qnica
У меня была опечатка в последнем ассерте.
Вообще это выдернута часть теста. В тесте между сохранениями дергается рест апи.
Суть этого фрагмента: сохранять в заданное время сущность и проверить что ее время обновления, то, в которое мы его сахранили.
4kpt_III
Сложновато Вы придумали. Я бы в тесте сохранил время создания и после обновления проверил бы, что времена не совпадают. Или нужна повышенная точность? Просто подмена для такого теста уж как-то слишком витиевато
qnica
Это приемочный тест. Хотелось бы в нем все механизмы отфиксировать.
Мне просто не понятно где именно нужен патч для datetime. Ведь если я подсовываю в самой модели лямюду в default то все работает нормально:
created = db.Column(db.DateTime(), default=lambda: datetime.now())

P.S. Еще вопрос немного не по теме. А как принудительно обновить запись если поля не менялись(что бы сработали только функции на onupdate)?
Я недавно начал использовать Flask+SQLAlchemy, до этого все проекты были на Django. И иногда возникает мысль: “Ага, на джанго я это делал так, а как мне это же сделать c алхимеей”. Хотя может это не совсем верный подход
sander
пропробуй явно время задать зачем freezegun
и зачем обновлять запись если поля не изменились?
qnica
По условию у каждой записи должн быть свой период актуализации. Когда запись “протухает” об этом оповещается клиент, который сверяет данные и если все нормально, то сохраняет запись, тем самым актуализируя ее.
В приемочном тесте я действую от роли пользователся, дергая рест апи. По этому я использую freezegun и стараюсь не вмешиваться в процессы создания записей руками.
4kpt_III
qnica
Мало того, что он неверный, он еще губителен.

По второму вопросу. Попробуйте метод .update(). Но Вы опять колдуете Неужели в объекте нет ни одного поля, которое можно было бы обновить и проверить. Запись хранит только время? Тогда спроектированная БД, как бы не было печально, неверна в принципе…
sander
qnica
не совсем понимаю что вы делаете
как происходит актуализация? изменение поля update?
что имеется в виду под оповещением клиента?
qnica
4kpt_III
Но Вы опять колдуете Неужели в объекте нет ни одного поля, которое можно было бы обновить и проверить. Запись хранит только время?
sander
как происходит актуализация? изменение поля update?

Наверное я не правильно выразился. По мимо времени есть другие поля, но содержимое их не менялось. Т.е. нужно принудительно их перезаписать.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB