模拟函数调用实际函数
mock function called actual function
我有 cassandra python 驱动程序的代码。
from cassandra.cqlengine.management import sync_table
def sync_my_tables():
print sync_table
print "*" * 80
sync_table(my_models.student)
当我尝试为此编写 UT 时,我使用 @patch
嘲笑了 sync_table
。
from unittest import TestCase
from mock import patch
class TestCassandraSetup(TestCase):
@patch('cassandra.cqlengine.management.sync_table', return_value=True)
def test_sync_my_tables(self, _):
from cassandra.cqlengine.management import sync_table
print "*"*80
print sync_table
print "*"*80
cass_setup.sync_my_tables()
patch
后调用实际函数报错
Traceback (most recent call last):
File "/venv/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
return func(*args, **keywargs)
File "/venv/tests/test_cassandra_setup.py", line 26, in test_sync_database_tables
cassandra_client.sync_database_tables()
File "/venv/code/cass_setup.py", line 18, in sync_my_tables
sync_table(my_tables.student)
File "/venv/lib/python2.7/site-packages/cassandra/cqlengine/management.py", line 200, in sync_table
cluster = get_cluster()
File "/venv/lib/python2.7/site-packages/cassandra/cqlengine/connection.py", line 182, in get_cluster
raise CQLEngineException("%s.cluster is not configured. Call one of the setup or default functions first." % __name__)
CQLEngineException: cassandra.cqlengine.connection.cluster is not configured. Call one of the setup or default functions first.
-------------------- >> begin captured stdout << ---------------------
********************************************************************************
<MagicMock name='sync_table' id='4490003152'>
********************************************************************************
<function sync_table at 0x10b8075f0>
********************************************************************************
在 print 语句中,它第一次打印 MagicMock
,但是当在实际代码中打印相同时,它打印实际函数而不是模拟对象。
为什么它在两者之间变化?
Python 不能模拟(替换)已经在模块范围内的东西。导入后,您无法从外部更改它。为了使代码可测试,您需要导入更高级别的模块并使用那里的方法,因为它只是一个可以更改的 属性。
from cassandra.cqlengine import management
def sync_my_tables():
print management.sync_table
print "*" * 80
management.sync_table(my_models.student)
通过这种方式 mock 能够在运行时替换函数(management.sync_table = MagicMock()
)。
在您的测试函数中,您在函数被替换后执行导入,因此它按预期工作。
使用补丁时,需要对使用的对象进行补丁。因此,如果 sync_my_tables
位于路径为 foo/bar/baz.py
的文件中,您将需要像这样调用补丁:
@patch('foo.bar.baz.sync_table')
def test_sync_table(self, _):
# test code
我有 cassandra python 驱动程序的代码。
from cassandra.cqlengine.management import sync_table
def sync_my_tables():
print sync_table
print "*" * 80
sync_table(my_models.student)
当我尝试为此编写 UT 时,我使用 @patch
嘲笑了 sync_table
。
from unittest import TestCase
from mock import patch
class TestCassandraSetup(TestCase):
@patch('cassandra.cqlengine.management.sync_table', return_value=True)
def test_sync_my_tables(self, _):
from cassandra.cqlengine.management import sync_table
print "*"*80
print sync_table
print "*"*80
cass_setup.sync_my_tables()
patch
后调用实际函数报错
Traceback (most recent call last):
File "/venv/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
return func(*args, **keywargs)
File "/venv/tests/test_cassandra_setup.py", line 26, in test_sync_database_tables
cassandra_client.sync_database_tables()
File "/venv/code/cass_setup.py", line 18, in sync_my_tables
sync_table(my_tables.student)
File "/venv/lib/python2.7/site-packages/cassandra/cqlengine/management.py", line 200, in sync_table
cluster = get_cluster()
File "/venv/lib/python2.7/site-packages/cassandra/cqlengine/connection.py", line 182, in get_cluster
raise CQLEngineException("%s.cluster is not configured. Call one of the setup or default functions first." % __name__)
CQLEngineException: cassandra.cqlengine.connection.cluster is not configured. Call one of the setup or default functions first.
-------------------- >> begin captured stdout << ---------------------
********************************************************************************
<MagicMock name='sync_table' id='4490003152'>
********************************************************************************
<function sync_table at 0x10b8075f0>
********************************************************************************
在 print 语句中,它第一次打印 MagicMock
,但是当在实际代码中打印相同时,它打印实际函数而不是模拟对象。
为什么它在两者之间变化?
Python 不能模拟(替换)已经在模块范围内的东西。导入后,您无法从外部更改它。为了使代码可测试,您需要导入更高级别的模块并使用那里的方法,因为它只是一个可以更改的 属性。
from cassandra.cqlengine import management
def sync_my_tables():
print management.sync_table
print "*" * 80
management.sync_table(my_models.student)
通过这种方式 mock 能够在运行时替换函数(management.sync_table = MagicMock()
)。
在您的测试函数中,您在函数被替换后执行导入,因此它按预期工作。
使用补丁时,需要对使用的对象进行补丁。因此,如果 sync_my_tables
位于路径为 foo/bar/baz.py
的文件中,您将需要像这样调用补丁:
@patch('foo.bar.baz.sync_table')
def test_sync_table(self, _):
# test code