1. ホーム
  2. パイソン

[解決済み】Pythonモックの複数の戻り値

2022-04-19 19:25:15

質問

pythonsのmock.patchを使っていて、呼び出しごとに戻り値を変えたいのですが、どうすればいいですか? ここで注意点があります。 パッチが適用される関数には入力がないので、入力に基づいて返り値を変更することはできません。

以下は参考までに私のコードです。

def get_boolean_response():
    response = io.prompt('y/n').lower()
    while response not in ('y', 'n', 'yes', 'no'):
        io.echo('Not a valid input. Try again'])
        response = io.prompt('y/n').lower()

    return response in ('y', 'yes')

私のテストコードです。

@mock.patch('io')
def test_get_boolean_response(self, mock_io):
    #setup
    mock_io.prompt.return_value = ['x','y']
    result = operations.get_boolean_response()

    #test
    self.assertTrue(result)
    self.assertEqual(mock_io.prompt.call_count, 2)

io.prompt は、単に "input" のプラットフォーム非依存版 (python 2 および 3) に過ぎません。つまり、最終的に私はユーザーの入力をモック化しようとしているのです。戻り値にリストを使おうとしましたが、うまくいきません。

もし戻り値が無効なものであれば、ここで無限ループに陥ることがおわかりいただけると思います。ですから、最終的に戻り値を変更して、テストが実際に終了するようにする方法が必要です。

(この質問に答える別の方法として、ユニットテストでユーザー入力を模倣する方法を説明することができます)


のダブりではありません。 この質問 主に、入力を変化させる機能がないためです。

のAnswerのコメントの1つに この質問 も同じような内容ですが、回答・コメントはありません。

解決方法を教えてください。

を割り当てることができます。 イテラブル から side_effect そして、モックは呼び出されるたびにその次の値を返します。

>>> from unittest.mock import Mock
>>> m = Mock()
>>> m.side_effect = ['foo', 'bar', 'baz']
>>> m()
'foo'
>>> m()
'bar'
>>> m()
'baz'

を引用しています。 Mock() ドキュメンテーション :

もし サイドエフェクト が反復可能である場合、モックを呼び出すたびに反復可能な値の次の値が返されます。