Pythonでmock
を使用するのはかなり困難です。
def method_under_test():
r = requests.post("http://localhost/post")
print r.ok # prints "<MagicMock name='post().ok' id='11111111'>"
if r.ok:
return StartResult()
else:
raise Exception()
class MethodUnderTestTest(TestCase):
def test_method_under_test(self):
with patch('requests.post') as patched_post:
patched_post.return_value.ok = True
result = method_under_test()
self.assertEqual(type(result), StartResult,
"Failed to return a StartResult.")
テストは実際には正しい値を返しますが、r.ok
はTrue
ではなく、モックオブジェクトです。 Pythonのmock
ライブラリの属性をどのようにモックしますか?
return_value
および PropertyMock
を使用する必要があります。
with patch('requests.post') as patched_post:
type(patched_post.return_value).ok = PropertyMock(return_value=True)
つまり、requests.post
を呼び出すとき、その呼び出しの戻り値で、プロパティPropertyMock
にok
を設定して、値True
を返します。
コンパクトで簡単な方法は、new_callable
patch
の属性を使用して、patch
の代わりにPropertyMock
を使用して、MagicMock
を使用してモックオブジェクトを作成することです。 patch
に渡される他の引数は、PropertyMock
オブジェクトの作成に使用されます。
with patch('requests.post', new_callable=PropertyMock, return_value=True) as mock_post:
"""Your test"""
モックバージョン '1.0.1'では、質問で言及されたより単純な構文がサポートされ、そのまま機能します!
更新されたサンプルコード(unittestの代わりにpy.testが使用されます):
import mock
import requests
def method_under_test():
r = requests.post("http://localhost/post")
print r.ok
if r.ok:
return r.ok
else:
raise Exception()
def test_method_under_test():
with mock.patch('requests.post') as patched_post:
patched_post.return_value.ok = True
result = method_under_test()
assert result is True, "mock ok failed"
このコードを実行するには:(必ずpytestをインストールしてください)
$ py.test -s -v mock_attributes.py
======= test session starts =======================
platform linux2 -- Python 2.7.10 -- py-1.4.30 -- pytest-2.7.2 -- /home/developer/miniconda/bin/python
rootdir: /home/developer/projects/learn/scripts/misc, inifile:
plugins: httpbin, cov
collected 1 items
mock_attributes.py::test_method_under_test True
PASSED
======= 1 passed in 0.03 seconds =================