2つのファイルがあります
spike.py
class T1(object):
def foo(self, afd):
return "foo"
def get_foo(self):
return self.foo(1)
def bar():
return "bar"
test_spike.py:
from unittest import TestCase
import unittest
from mock import patch, MagicMock
from spike import T1, bar
class TestStuff(TestCase):
@patch('spike.T1.foo', MagicMock(return_value='patched'))
def test_foo(self):
foo = T1().get_foo()
self.assertEqual('patched', foo)
@patch('spike.bar')
def test_bar(self, mock_obj):
mock_obj.return_value = 'patched'
bar = bar()
self.assertEqual('patched', bar)
if __name__ == "__main__":
unittest.main()
python test_spike.py
を実行すると、最初のテストケースはパスしますが、2番目のテストケースは失敗します。 nosetests test_spike.py
を使用するように切り替えると、2つとも失敗します。
どうしてこうなったのか分かりませんか?これらのケースはすべて通過するはずです。
test_fooの場合、パッチは正しく使用されていません。次のように使用する必要があります。
class TestFoo(TestCase):
@patch.object(T1, 'foo', MagicMock(return_value='patched'))
def test_foo(self):
foo = T1().get_foo()
self.assertEqual('patched', foo)
それは私に与えます:
nosetests test_spike.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
ここで、2番目の例は、bar関数をインポートし(それへの参照を取得)、それをモックしようとしているため機能しません。何かをあざけるとき、変数が保持するものを変更することはできません(元の関数への参照)。これを修正するには、次のような@falsetruの推奨方法を使用する必要があります。
from unittest import TestCase
import unittest
from mock import patch
import spike
class TestFoo(TestCase):
@patch('spike.bar')
def test_bar(self, mock_obj):
mock_obj.return_value = 'patched'
value = spike.bar()
self.assertEqual('patched', value)
if __name__ == "__main__":
unittest.main()
これは私に与えます:
python test_spike.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
しかし、それを鼻で実行しようとすると、次のようになります。
nosetests test_spike.py
F
======================================================================
FAIL: test_bar (src.test_spike.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/zilva/envs/test/local/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
return func(*args, **keywargs)
File "/home/zilva/git/test/src/test_spike.py", line 11, in test_bar
self.assertEqual('patched', value)
AssertionError: 'patched' != 'bar'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
これは、適切な場所にパッチを適用していないために起こります。私のディレクトリ構造は:
test/
└── src/
├── spike.py
├── test_spike.py
└── __init__.py
私はsrcディレクトリからテストを実行するので、次のようにプロジェクトのルートディレクトリからのパスを使用してパッチを適用する必要があります。
@patch('src.spike.bar')
そしてこれは私に与えるでしょう:
nosetests test_spike.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
または私がテストディレクトリにいる場合:
nosetests src/test_spike.py
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
spike.bar
を使用してbar
にアクセスします。インポートされたbar
はmock.patch
の影響を受けません。
from unittest import TestCase
import unittest
from mock import patch, MagicMock
from spike import T1
import spike # <----
class TestShit(TestCase):
@patch('spike.T1.foo', MagicMock(return_value='patched'))
def test_foo(self):
foo = T1().get_foo()
self.assertEqual('patched', foo)
@patch('spike.bar')
def test_bar(self, mock_obj):
mock_obj.return_value = 'patched'
bar = spike.bar() # <-----
self.assertEqual('patched', bar)
if __name__ == "__main__":
unittest.main()