模拟函数称为实际函数

时间:2016-06-15 00:44:17

标签: python cassandra mocking python-unittest

我有cassandra python驱动程序的代码。

from cassandra.cqlengine.management import sync_table

def sync_my_tables():
    print sync_table
    print "*" * 80
    sync_table(my_models.student)

当我尝试为此编写UT时,我使用sync_table嘲笑@patch

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,但在实际代码中打印时,它会打印实际函数而不是模拟对象。

乳清之间的变化?

2 个答案:

答案 0 :(得分:1)

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())。

在测试功能中,您在更换功能后进行导入,以便按预期工作。

答案 1 :(得分:1)

使用补丁时,您需要修补使用补丁的对象。因此,如果sync_my_tables位于路径为foo/bar/baz.py的文件中,则需要调用此类补丁:

@patch('foo.bar.baz.sync_table')
def test_sync_table(self, _):
    # test code