如何mock.patch MySQLdb.cursors?

时间:2015-02-05 13:49:20

标签: python unit-testing mocking

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'对象没有属性'cursors'

我找到了一种方法:

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

from MySQLdb.cursors import DictCursor

然后我不再收到错误,我甚至不必mock.patch MySQLdb包装器:

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

对解决方案不太满意。一般来说,我在模拟我的项目之外的类(例如生活在virtualenv中)时遇到困难。我保持开放,所以希望有人可以告诉我如何模拟这类课程。

1 个答案:

答案 0 :(得分:2)

首先:确保<{1}}

中有
Database.py

否则,即使您没有修补任何内容,也会引发您提到的错误。如果要进行双重检查,请在import MySQLdb.cursors 的顶部添加cur=MySQLdb.cursors.DictCursor并删除所有修补程序:您将在新行中发现相同的错误。如果您在尝试指向__init__之前在上下文中的某处加载MySQLdb.cursors,则该错误将消失。如果您想知道之前没有看到该错误,是因为在您的生产代码中,您在使用MySQLdb.cursors.DictCursor之前导入了MySQLdb.cursors

现在进行测试,你的构造函数将通过,CanonDatabase() evil 函数不尝试连接任何东西只需修补create_connection和其他任何内容即可获得:

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) ,你可以装饰测试类。