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

Чтобы добавить к сказанному, Python 3.4 представил менеджер контекста contextlib.redirect_stdout . Он принимает файл (-образный) объект, к которому должен быть перенаправлен вывод.

Перенаправление на / dev / null будет подавлять вывод:

In [11]: def f(): print('noise')

In [12]: import os, contextlib

In [13]: with open(os.devnull, 'w') as devnull:
   ....:     with contextlib.redirect_stdout(devnull):
   ....:         f()
   ....:         

In [14]: 

Это решение может быть адаптировано для использования в качестве декоратора:

import os, contextlib

def supress_stdout(func):
    def wrapper(*a, **ka):
        with open(os.devnull, 'w') as devnull:
            with contextlib.redirect_stdout(devnull):
                func(*a, **ka)
    return wrapper

@supress_stdout
def f():
    print('noise')

f() # nothing is printed

Другое возможное и иногда полезное решение, которое будет работать как в Python 2, так и в 3, должно пройти / dev / null в качестве аргумента f и перенаправить вывод с использованием аргумента file функции print :

In [14]: def f(target): print('noise', file=target)

In [15]: with open(os.devnull, 'w') as devnull:
   ....:     f(target=devnull)
   ....:     

In [16]: 

Вы даже можете сделать target полностью необязательным:

def f(target=sys.stdout):
    # Here goes the function definition

Обратите внимание: вам нужно будет

from __future__ import print_function

в Python 2.

20
задан Shailendra 5 May 2010 в 14:29
поделиться

5 ответов

Зачем вам имитировать внутренний метод?

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

Инверсия управления и Внедрение зависимостей - это некоторые возможные стратегии проектирования, которые могут уменьшить взаимосвязь и повысить согласованность ваших классов и устранить необходимость имитировать внутренние методы.

Я не верю, что существует четкий путь к непубличному высмеиванию Moq.

Но, если вам это абсолютно необходимо, вы можете использовать TypeMock Isolator , чтобы имитировать что угодно.

Кроме того, чтобы не затеряться в гуле: Томас связал хорошую статью об использовании бесплатных MS Moles для издевательства над непубличными участниками.

Издевательство над неизлечимым: использование Microsoft Moles с Gallio

0
ответ дан 29 November 2019 в 22:28
поделиться

Если вам нужно протестировать много кода, который вы не можете изменить, то лучше с самого начала использовать MS Moles или TypeMock.

Бесплатные mocking-фреймворки, такие как Moq, в любом случае дают вам поддержку только интерфейсов и виртуальных методов. Не похоже, что вы далеко пойдете с этим...

Thomas

0
ответ дан 29 November 2019 в 22:28
поделиться

Не с Moq.

Но вы можете использовать бесплатный фреймворк Moles от MS для таких вещей. Я писал об этом здесь: Mocking the Unmockable: Using Microsoft Moles with Gallio. (это относится не только к Gallio, но это дает хорошее общее впечатление о том, что можно сделать с Moles...). Другой альтернативой может быть Typemock...

HTH. Thomas

3
ответ дан 29 November 2019 в 22:28
поделиться

Юнит-тестирование должно проверять интерфейс класса. Вы можете высмеивать зависимости, но детали реализации самого класса (такие как приватные методы) должны тестироваться как часть всего класса, а не отдельно, и не должны изменяться для тестирования (иначе вы будете тестировать не тот модуль, который действительно будет использоваться).

Если вы чувствуете, что необходимо изменить метод, чтобы сделать класс тестируемым, рефакторите класс так, чтобы сложная часть стала зависимостью, или иным образом заменяемой параметром или подклассом.

1
ответ дан 29 November 2019 в 22:28
поделиться

Вы можете легко имитировать внутренние виртуальные методы, добавив следующее в свой AssemblyInfo.cs:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] // namespace in Moq
[assembly: InternalsVisibleTo("YourTestClass")]

Если ваша сборка строго названа, вам необходимо включить открытый ключ для DynamicProxyGenAssembly2 (Спасибо за комментарий @ bvgheluwe; источник: Moq краткое руководство ) :

[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2,PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

Я не понимаю, почему в принятом ответе говорится, что вы никогда не должны этого делать. Разве это не то, что вы делаете, когда используете технику внедрения зависимостей «Извлечь и переопределить» (локальный фабричный метод), описанную Роем Ошеровым в главе 3 книги «Искусство модульного тестирования» ?

{{1 }}
61
ответ дан 29 November 2019 в 22:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: