【问题标题】:Connection.commit() does not persist data in Django TestConnection.commit() 不会在 Django 测试中保留数据
【发布时间】:2019-11-06 07:10:26
【问题描述】:

我正在尝试测试我的 db_insert() 方法是否有效。

def db_insert(data, insert_query, limit=100):
    """Persist data to database
    :param data: Tuple of tuples
    :param insert_query: String
    :param limit: Integer
    """
    # Insert / Merge
    cursor = conn.cursor()
    try:
        for i in range(0, int(len(data) / limit) + 1):
            sliced_data = data[i * limit:i * limit + limit]
            if sliced_data:
                cursor.executemany(insert_query, sliced_data)
                conn.commit()
    except Exception as e:
        conn.rollback()
        raise DBException('ScriptName:db_manager.py,ErrorType:{}Impact:Unable to insert into database,'
                          'ErrorMessage:{}'.format(type(e).__name__, e))

这个方法被另一个方法调用:

def insert(cls, new_list):
    """Insert new data to DB
    :param new_list: List
    """
    try:
        insert_query = "insert into TABLE {} values {}" \
            .format(tuple(cls.TABLE_ATTR[1:]), ('%s',) * len(cls.TABLE_ATTR[1:]))
        insert_query = insert_query.replace('\'', '')
        db_insert(new_list, insert_query)
    except Exception as e:
        logger.exception(e)

最后,insert() 方法由 TestCase 子类中的测试调用:

def test_insert_method_success(self):
        SomeModule.insert(['text1', 'text2', 'text3', 1, settings.SCRIPT_RUN_TIME])
        cursor = conn.cursor()
        cursor.execute("select * from TABLE")
        data = cursor.fetchall()
        print(data)  # [1]

[1] 中的输出确实返回 2 个元组。然而,这些元组是使用 models.save()setUp() 中添加到数据库中的数据。

有人能告诉我为什么conn.commit() 在实际运行中没有按预期将数据持久化到数据库中吗?

【问题讨论】:

  • tests 为您创建一个新数据库并运行测试并在完成后擦除
  • 是的,实际的表有更多的数据。但是这两个返回的元组是在测试运行期间添加的数据
  • cursor = conn.cursor() conn 来自哪里?

标签: python django django-models transactions database-connection


【解决方案1】:

您的测试失败了,因为它在 Django TestCase 中运行。该类使用事务作为运行然后回滚测试的机制。由于每个测试都在事务中运行,因此任何在测试中手动管理事务的尝试(例如您的conn.commit()conn.rollback())都会造成严重破坏。

对于这样的测试,您应该改用TransactionTestCase。使用表截断来撤消数据库影响;它速度较慢,但​​不会影响您管理事务的能力。

详情请见the documentation

Django 的TestCase 类是TransactionTestCase 的一个更常用的子类,它利用数据库事务工具来加快在每次测试开始时将数据库重置为已知状态的过程。然而,这样做的结果是某些数据库行为无法在 Django TestCase 类中进行测试....

TransactionTestCase [不像TestCase] 可以调用提交和回滚,并观察这些调用对数据库的影响。

【讨论】:

    猜你喜欢
    • 2019-10-04
    • 1970-01-01
    • 2015-08-10
    • 2011-09-23
    • 2018-08-17
    • 1970-01-01
    • 2011-06-04
    • 1970-01-01
    • 2015-10-27
    相关资源
    最近更新 更多