*args
и **kwargs
- общая идиома, позволяющая произвольному количеству аргументов функциям, описанным в разделе , больше о определении функций в документации Python.
] *args
предоставит вам все функциональные параметры как кортеж :
In [1]: def foo(*args):
...: for a in args:
...: print a
...:
...:
In [2]: foo(1)
1
In [4]: foo(1,2,3)
1
2
3
**kwargs
предоставит вам все аргументы ключевого слова, кроме тех, которые соответствуют формальному параметру как словарь.
In [5]: def bar(**kwargs):
...: for a in kwargs:
...: print a, kwargs[a]
...:
...:
In [6]: bar(name='one', age=27)
age 27
name one
Оба идиома могут быть смешаны с нормальными аргументами, чтобы разрешить набор фиксированных и некоторых переменных:
def foo(kind, *args, **kwargs):
pass
Другое использование *l
idiom - распаковывать списки аргументов при вызове функции.
In [9]: def foo(bar, lee):
...: print bar, lee
...:
...:
In [10]: l = [1,2]
In [11]: foo(*l)
1 2
В Python 3 можно использовать *l
в левой части задания ( Extended Iterable Unpacking ), хотя в этом контексте он содержит список вместо кортежа:
first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]
Также Python 3 добавляет новую семантику (см. PEP 3102 ):
def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
pass
Такая функция принимает только 3 позиционных аргумента, и все после *
может быть передано только как аргументы ключевого слова .
Я использовал Wrapper, чтобы обойти эту проблему. Создайте объект-обертку и передайте свой издеваемый метод.
См. Издевательские статические методы для модульного тестирования Paul Irwin, у него есть хорошие примеры.
Я обнаружил, что мне пришлось обнаружить внутреннюю часть метода расширения, который я пытался издеваться над входом, и издеваться над тем, что происходило внутри расширения.
Я просмотрел с использованием расширения, добавив добавление кода непосредственно к вашему методу. Это мне не нужно было издеваться над тем, что происходит внутри расширения, а не с самим расширением.
Мне нравится использовать обертку (шаблон адаптера), когда я обертываю сам объект. Я не уверен, что использую это для переноса метода расширения, который не является частью объекта.
Я использую внутреннее Lazy Injectable Property любого типа Action, Func, Predicate или делегата и (g3)
internal Func<IMyObject, string, object> DoWorkMethod
{
[ExcludeFromCodeCoverage]
get { return _DoWorkMethod ?? (_DoWorkMethod = (obj, val) => { return obj.DoWork(val); }); }
set { _DoWorkMethod = value; }
} private Func<IMyObject, string, object> _DoWorkMethod;
Затем вы вызываете Func вместо фактического метода.
public object SomeFunction()
{
var val = "doesn't matter for this example";
return DoWorkMethod.Invoke(MyObjectProperty, val);
}
Для более полного примера , проверьте http://www.rhyous.com/2016/08/11/unit-testing-calls-to-complex-extension-methods/
Вы не можете «прямо» высмеять статический метод (следовательно, метод расширения) с насмешливой структурой. Вы можете попробовать Moles ( http://research.microsoft.com/en-us/projects/pex/downloads.aspx ), бесплатный инструмент от Microsoft, который реализует другой подход. Ниже приведено описание инструмента:
Moles - это легкая структура для тестовых заглушек и обходов в .NET, основанная на делегатах.
Моли могут использоваться для обхода любой метод .NET, в том числе не виртуальные / статические методы в закрытых типах.
blockquote>Вы можете использовать Moles с любой тестовой средой (независимо от этого).