Как смоделировать класс Python, чтобы изменить только один аргумент - PullRequest
0 голосов
/ 05 июня 2019

Мне нужно обернуть класс в макет примерно так:

Оригинальный код:

class _InnerImpl(object):

  def __init__(self, arg1, arg2, arg3):
    # do stuff

Я хотел бы сделать что-то вроде этого:

from unittest.mock import patch

def my_wrapper(*args, **kwargs):
  kwargs['arg1'] = gen_next_value()  # change one of the arguments
  return _InnerImpl(*args, **kwargs)  # call the real thing with modified args

def run(user_input):
  with patch(_InnerImpl, my_wrapper):
     some_method(user_input)
* 1008К сожалению, как работает patch, я не могу назвать «реальную вещь», потому что она также вызывается внутри блока with patch.Это приводит к бесконечному циклу рекурсии.

Я использую это в реализации вне модульного теста.Так что это не для юнит-тестов.Я пробовал разные вещи, такие как сохранение __init__ ссылки, используя wraps.Ничего не работает.

1 Ответ

0 голосов
/ 06 июня 2019

Я предлагаю не использовать макеты для вещей, которые не являются юнит-тестами. Если я понимаю ваш пример, кажется, что вам нужен шаблон фабричного метода https://en.wikipedia.org/wiki/Factory_method_pattern

Если вы не можете изменить код, который вы исправляете, попробуйте использовать другое пространство имен. например, с заданным целевым кодом a.py

class A(object):
    def __init__(self, v):
        print('A({})'.format(v))

def foo():
    y = A('a')

вы могли бы написать b.py

from unittest.mock import patch
from a import A,foo
def my_wrapper(*args, **kwargs):
    return A('b')
def bar():
    with patch('a.A', my_wrapper):
        foo()
...