Connection.commit () не сохраняет данные в тесте Django - PullRequest
0 голосов
/ 06 ноября 2019

Я пытаюсь проверить, работает ли мой метод 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() не сохраняет данные в базе данных, как ожидалось в реальном прогоне

1 Ответ

0 голосов
/ 13 ноября 2019

Ваш тест не пройден, потому что он работает внутри Django TestCase. Этот класс использует транзакции в качестве механизма для запуска, а затем отката тестов. Поскольку каждый тест выполняется внутри транзакции, любая попытка вручную управлять транзакциями внутри теста (например, вашими conn.commit() и conn.rollback()) приведет к хаосу.

Для таких тестов вы должны вместо этого использовать TransactionTestCase. Это использует усечение таблицы для отмены эффектов базы данных;это медленнее, но не мешает вашей способности управлять транзакциями.

См. документацию для получения более подробной информации:

Класс TestCase Джанго - это наиболее часто используемый подкласс TransactionTestCase, который использует средства транзакций базы данных. ускорить процесс сброса базы данных до известного состояния в начале каждого теста. Следствием этого, однако, является то, что некоторые поведения базы данных не могут быть протестированы в классе Django TestCase ....

A TransactionTestCase [в отличие от TestCase] может вызывать commit и rollback и наблюдатьвлияние этих вызовов на базу данных.

...