Как имитировать запрос «with connect» SQL в модульном тестировании Python 3? - PullRequest
1 голос
/ 05 мая 2020

Для функции, подобной приведенной ниже, где механизмом является механизм SQLAlchemy, например:

from sqlalchemy import create_engine
engine = create_engine(f'mysql+pymysql://{db_username}:{db_password}@{db_host}:{db_port}/{db_name}', pool_recycle=3600)
def pull(engine, afield):
    query = f"SELECT col1, col2 FROM mydatabase WHERE field='{afield}'"
    with engine.connect() as conn:
        result = conn.execute(query)
    return result

Как издеваться над результатом запроса из оператора «with» в модульном тесте?

1 Ответ

1 голос
/ 05 мая 2020

Предполагая, что указанная выше функция находится в файле с именем datapull.py и находится в том же каталоге, что и этот код модульного теста, ниже приведен пример имитации результата SQL.

Мокинг движка и соединение довольно просты, но имитируя двигатель, чтобы return соединение было сложнее.

Оператор with (описанный для Python 3 здесь ) возвращает соединение после того, как __enter__ вызывается в движке.

Таким образом, mock_engine.connect.return_value.__enter__.return_value = mock_conn будет правильно возвращать фиктивное соединение в приведенном выше коде with.

import mock
import unittest
import datapull


class TestQueryRDS(unittest.TestCase):
    def test_happy_day(self):
        """Test happy day query"""
        mock_conn = mock.MagicMock()
        mock_conn.execute.return_value = [['c1', 'c2'], ['a1', 'a2']]
        mock_engine = mock.MagicMock()
        mock_engine.connect.return_value.__enter__.return_value = mock_conn
        actual = datapull.pull(mock_engine, '1234abcd')
        assert actual == [['c1', 'c2'], ['a1', 'a2']]
        exp_sql = "SELECT col1, col2 FROM mydatabase WHERE field='1234abcd'"
        mock_conn.execute.assert_called_once_with(exp_sql)
...