[解決済み] あるメソッドが複数の引数のうち1つの引数で呼び出されたことを保証する
質問
への呼び出しをモックにしています。
requests.post
への呼び出しをモックしています。
Mock
ライブラリを使っています。
requests.post = Mock()
呼び出しには複数の引数が含まれます: URL、ペイロード、いくつかの認証関連などです。私は以下のことを主張したい
requests.post
が特定の URL で呼び出されたことを主張したいのですが、 他の引数については気にしません。これを試すと
requests.post.assert_called_with(requests_arguments)
の場合、その引数のみで呼ばれることを想定しているため、テストは失敗します。
他の引数を渡すことなく、関数呼び出しのどこかで単一の引数が使用されているかどうかをチェックする方法はありますか?
あるいは、さらに良い方法として、特定の URL をアサートして、他の引数のデータ型を抽象化する方法はありますか (例: data は辞書でなければならない、auth は HTTPBasicAuth のインスタンスでなければならない、など)。
どのように解決するのですか?
私の知る限りでは
Mock
を介して望むことを実現する方法を提供しません。
assert_called_with
. にアクセスすることができます。
call_args
と
call_args_list
のメンバーで構成され、アサーションを手動で実行します。
しかし、簡単な(そして汚い)方法で
ほぼ
を実現する簡単な(汚い)方法があります。を持つクラスを実装する必要があります。
__eq__
メソッドは常に
True
:
def Any(cls):
class Any(cls):
def __eq__(self, other):
return True
return Any()
として使う。
In [14]: caller = mock.Mock(return_value=None)
In [15]: caller(1,2,3, arg=True)
In [16]: caller.assert_called_with(Any(int), Any(int), Any(int), arg=True)
In [17]: caller.assert_called_with(Any(int), Any(int), Any(int), arg=False)
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-17-c604faa06bd0> in <module>()
----> 1 caller.assert_called_with(Any(int), Any(int), Any(int), arg=False)
/usr/lib/python3.3/unittest/mock.py in assert_called_with(_mock_self, *args, **kwargs)
724 if self.call_args != (args, kwargs):
725 msg = self._format_mock_failure_message(args, kwargs)
--> 726 raise AssertionError(msg)
727
728
AssertionError: Expected call: mock(0, 0, 0, arg=False)
Actual call: mock(1, 2, 3, arg=True)
見ての通り、これは単に
arg
. のサブクラスを作成する必要があります。
int
のサブクラスを作らなければなりません。そうしないと、比較はうまくいきません。
1
. しかし、あなたはまだすべての引数を提供する必要があります。もし多くの引数がある場合は、タプルアンパッキングを使ってコードを短くすることができます。
In [18]: caller(1,2,3, arg=True)
In [19]: caller.assert_called_with(*[Any(int)]*3, arg=True)
これ以外には、すべてのパラメータを
assert_called_with
にすべてのパラメータを渡さず、意図したとおりに動作させる方法は思いつきません。
上記の解決策は、他の引数のタイプをチェックするために拡張することができます。例えば
In [21]: def Any(cls):
...: class Any(cls):
...: def __eq__(self, other):
...: return isinstance(other, cls)
...: return Any()
In [22]: caller(1, 2.0, "string", {1:1}, [1,2,3])
In [23]: caller.assert_called_with(Any(int), Any(float), Any(str), Any(dict), Any(list))
In [24]: caller(1, 2.0, "string", {1:1}, [1,2,3])
In [25]: caller.assert_called_with(Any(int), Any(float), Any(str), Any(dict), Any(tuple))
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-25-f607a20dd665> in <module>()
----> 1 caller.assert_called_with(Any(int), Any(float), Any(str), Any(dict), Any(tuple))
/usr/lib/python3.3/unittest/mock.py in assert_called_with(_mock_self, *args, **kwargs)
724 if self.call_args != (args, kwargs):
725 msg = self._format_mock_failure_message(args, kwargs)
--> 726 raise AssertionError(msg)
727
728
AssertionError: Expected call: mock(0, 0.0, '', {}, ())
Actual call: mock(1, 2.0, 'string', {1: 1}, [1, 2, 3])
のような引数は許されません。
int
または
str
. への複数の引数を許可する
Any
に複数の引数を許可し、多重継承を使用しても解決しません。これを解決するには
abc.ABCMeta
def Any(*cls):
class Any(metaclass=abc.ABCMeta):
def __eq__(self, other):
return isinstance(other, cls)
for c in cls:
Any.register(c)
return Any()
例
In [41]: caller(1, "ciao")
In [42]: caller.assert_called_with(Any(int, str), Any(int, str))
In [43]: caller("Hello, World!", 2)
In [44]: caller.assert_called_with(Any(int, str), Any(int, str))
1
という名前を使いました。
Any
という名前にしました。これは、コード内でクラスとして使用されているからです。また
any
はビルトインです...
関連
-
[解決済み] Mockitoを使用して特定のメソッドが呼び出されていないことを確認するにはどうすればよいですか?
-
[解決済み] Mockito : メソッド内で生成されたオブジェクトでメソッドが呼び出されたことを確認する方法?
-
[解決済み】Mockitoの汎用 "any() "メソッドを使用する。
-
[解決済み] Mockを使用して関数/メソッドが呼び出されていないことを確認する
-
[解決済み] Entity Framework 6のユニットテストはどうなっているのか、気になりますか?
-
[解決済み] バブルソートの宿題
-
[解決済み] タプルのリストを複数のリストに変換するには?
-
[解決済み] 異なる順序で同じ要素を持つ2つのJSONオブジェクトを等しく比較するには?
-
[解決済み] Pythonの辞書にあるスレッドセーフについて
-
[解決済み] Pythonで2つの順序付きリストを比較するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] googletransがエラー 'NoneType' オブジェクトに 'group' 属性がない、と言って動かなくなった。
-
[解決済み] Python 3でバイナリデータを標準出力に書き込むには?
-
[解決済み] SQLAlchemy: 日付フィールドをフィルタリングする方法は?
-
[解決済み] データフレームをソートした後にインデックスを更新する
-
[解決済み] Django 1.7で初期マイグレーションからマイグレートバックする方法は?
-
[解決済み] 異なる順序で同じ要素を持つ2つのJSONオブジェクトを等しく比較するには?
-
[解決済み] Flask でグローバル変数はスレッドセーフか?リクエスト間でデータを共有するには?
-
[解決済み] Pythonの文字列書式をリストで使う
-
[解決済み] PythonのRequestsモジュールを使ってWebサイトに "ログイン "するには?
-
[解決済み] djangoのQueryDictをPythonのDictに変更するには?