вызовы функции имитации python, которые вызываются во время импорта модуля

Мне нужно выполнить издевательство над кодом Python, который выполняется во время импорта модуля.

Например, у меня есть такой код

import configparser

config = configparser.ConfigParser()
config.read('test.ini')
a = float(config['config']['a'])
b = float(config['config']['b'])
c = float(config['config']['c'])

print(a)
print(b)
print(c)

Мне нужен фиктивный "конфиг" для тестирования

import pytest
import mock

import app

@mock.patch('app.configparser.ConfigParser')
def test_config_mock(config_mock):
     config_mock.return_value = {'config': { 'a' : 1 } }

Однако эта функция тестирования вызывается после фактического импорта, поэтому мои насмешки не имеют никакого смысла.

Каков правильный способ делать такие вещи?


person libxelar.so    schedule 29.12.2019    source источник
comment
Правильный способ сделать это просто не при импорте. Предоставьте функцию, которая это делает, а затем назовите ее if __name__ == •"__main__":.   -  person jonrsharpe    schedule 29.12.2019
comment
@jonrsharpe, извините, я не уверен, что понимаю, как насмешливый вопрос связан с вашим ответом. Если я поставлю оператор импорта в функцию и вызову функцию из if name == main, я столкнусь с той же проблемой. Модуль будет загружен до фактического выполнения тестовой функции.   -  person libxelar.so    schedule 30.12.2019
comment
Я не говорю о том, чтобы импортировать функцию в тесте, если вы это имеете в виду; Я говорю изменить app.configparser, чтобы вы могли импортировать его функции без немедленного выполнения.   -  person jonrsharpe    schedule 30.12.2019
comment
@jonsharpe, хорошо, теперь ясно, вы имеете в виду изменить тестируемый код. Но опять же, кажется, что это тоже не сработает. Переменные A,B,C будут определены только в области видимости if, но они будут использоваться в других функциях этого модуля. Это означает рефакторинг кода модуля, что не является благоприятным вариантом. Не могли бы вы опубликовать фрагмент кода (может быть, псевдокод), если это возможно?   -  person libxelar.so    schedule 30.12.2019
comment
Конечно, это означает рефакторинг кода модуля. Вы написали код, который невозможно протестировать; если вы хотите протестировать его, вам нужно будет его реорганизовать.   -  person jonrsharpe    schedule 30.12.2019
comment
Я не говорю, что эта модель хороша. Но что вы можете сделать, так это издеваться над экземпляром config вместо этого. Затем код, использующий эту конфигурацию, должен уловить насмешку.   -  person Mattias    schedule 31.12.2019
comment
это то, что я на самом деле сделал :) спасибо за ответ, хотя   -  person libxelar.so    schedule 05.01.2020


Ответы (1)


Что вы можете сделать в этом случае, так это исправить экземпляр config, используя mock.patch.dict:

# test_coolio.py
import mock
from app.fun import coolio


@mock.patch.dict('app.configparser.config', values={'config': {'a': 15}})
def test_config_mock():
    assert coolio() == '15'


# app/fun.py
from app.configparser import config


def coolio():
    return config['config']['a']

person Mattias    schedule 31.12.2019