我有两个文件
spike.py
class T1(object):
def foo(self, afd):
return "foo"
def get_foo(self):
return self.foo(1)
def bar():
return "bar"
testrongpike.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
时,第一个测试用例会通过,但第二个会失败。并且我切换到使用nosetests test_spike.py
,则两者都失败。
我不明白这是怎么发生的?这些案子应该全部通过。
使用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()
对于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
现在第二个例子不起作用,因为你导入了bar函数(获得了对它的引用),然后试图模拟它。当你模拟某个东西时,你不能改变你的变量(对原始函数的引用)。要解决这个问题,你应该使用@falstru建议的方法,比如:
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
为了详细说明最有用的答案,让我转述unittest.mock.的官方文档
a.py
class SomeClass:
...
b.py
import a
from a import SomeClass
def some_function():
a.SomeClass()
SomeClass()
如果您写入mock.patch('a.SomeClass')
,这将影响some_function
的第一行。如果您编写mock.patch('b.SomeClass')
,这将影响第二行。