Как издеваться над классом Python во время тестирования для проверки набора текста во время выполнения?

#python #python-mock #python-typing

Вопрос:

У меня есть некоторый метод приложения, который использует @typeguard.typechecked декоратор для выполнения проверок во время выполнения переданных параметров:

 class SalesDeal:
    pass

@typechecked
def do_something(deal: SalesDeal):
   pass
 

Внутри теста у меня есть поддельный класс FakeSalesDeal , который реализует минимальный макет для SalesDeal (что на самом деле очень сложный класс):

 class FakeSalesDeal:
    pass


def test_foo():
    deal = FakeSalesDeal()
    do_something(deal)
 

Этот тест, конечно, не пройдет, потому @typechecked что декоратор выдаст ошибку из-за другого класса.

Есть ли способ издеваться/подделывать класс FakeSalesDeal , чтобы пройти тест?

Комментарии:

1. Вы думали о том FakeSalesDeal , чтобы наследовать от SalesDeal и просто инициализировать его с помощью множества фиктивных значений (избегая сложных аспектов SalesDeal )?

2. Да, это тоже работает.

Ответ №1:

Вы можете использовать MagicMock с spec установленным значением SalesDeal вместо создания поддельного класса.

isinstance(mock, SalesDeal) будет True для этого макетного объекта, и вы должны быть в состоянии обойти проверку типа.

 from unittest.mock import MagicMock

# ...

def test_foo():
    deal = MagicMock(spec=SalesDeal)
    print(isinstance(deal, SalesDeal))
    do_something(deal)

test_foo()
 

Это печатает:

 True
 

amp; не выдает никаких ошибок проверки типа.

Это работает, потому typechecked что явно проверяет наличие Mock объектов, передаваемых с:

     if expected_type is Any or isinstance(value, Mock):
        return
 

Код отсюда

Так что, если вы используете правильные насмешки, typechecked это не должно вызывать у вас никаких проблем.

Комментарии:

1. Спасибо за указатель. Также можно наследовать от MagicMock и затем передавать проверки типов..своего рода обход, но это решает проблему.

Ответ №2:

Мое окончательное решение:

 class FakeSalesDeal(MagicMock):
    pass