如何mock.patchMySQLdb.cursors?

How to mock.patch MySQLdb.cursors?

class CanonDatabase:
    def __init__(self, clean_up_db=False):
        self.db = "tmg_canon_april_tokens"
        self.conn = create_connection(self.db)
        self.cur = self.conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)

我正在尝试 mock.patch MySQLdb 以便传递构造函数。

@mock.patch.object(MySQLdb, '__init__')
class TestDatabase(unittest.TestCase):
    def setUp(self):
        super(TestDatabase, self).setUp()
        patch = mock.patch('atone_canon.Database.create_connection')
        mock_baz = patch.start()
        mock_baz.cursor.return_value = mock.MagicMock()

    def tearDown(self):
        super(TestDatabase, self).tearDown()
        mock.patch.stopall()

    def test_clean_table(self, mysql_mock):
        db = CanonDatabase()
        self.assertEqual(True, False)

但是失败并显示以下错误消息:

File "atone_canon/Database.py", line 20, in __init__ self.cur = self.conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)

AttributeError: 'module' object has no attribute 'cursors'

我找到了一个方法:

如果我在我的单元测试中插入这个导入,甚至没有(!)使用它:

from MySQLdb.cursors import DictCursor

然后我不再收到错误,我什至不需要 mock.patch MySQLdb 包装器:

# @mock.patch.object(MySQLdb, '__init__')
class TestDatabase(unittest.TestCase):
   ...

对解决方案不太满意。通常我很难模拟生活在我项目之外的 类 (例如生活在 virtualenv 中)。我把这个打开了,所以希望有人能告诉我如何模拟这种 类.

首先:确保你在Database.py

import MySQLdb.cursors

否则,即使您不修补任何内容,也会出现您提到的错误。如果你想仔细检查它在 __init__ 的顶部添加 cur=MySQLdb.cursors.DictCursor 并删除所有补丁:你会发现在新行中出现相同的错误。如果您在尝试指向 MySQLdb.cursors.DictCursor 之前在上下文中的某处加载 MySQLdb.cursors,则该错误将消失。如果您想知道之前没有看到该错误是因为在您的生产代码中您在使用 CanonDatabase()

之前导入了 MySQLdb.cursors

现在做一个测试,你的构造函数将通过 create_connection evil 函数不要尝试连接任何东西都可以通过修补 create_connection 以及其他:

class TestSimpler(unittest.TestCase):
    @mock.patch('atone_canon.Database.create_connection')
    def test_base(self, mock_create_connection):
        db = CanonDatabase()
        self.assertIsNotNone(db)

当然你可以装饰测试class如果你想要补丁create_connection每个测试方法。