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)
I am trying to mock.patch MySQLdb in order to pass the constructor.
@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)
However this fails with the following error message:
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'
I found a way:
If I insert this import in my unit test, without (!) even using it:
from MySQLdb.cursors import DictCursor
Then I no longer get the error, and I won't even have to mock.patch the MySQLdb wrapper:
# @mock.patch.object(MySQLdb, '__init__')
class TestDatabase(unittest.TestCase):
...
Not too happy with the solution. Generally I have difficulties with mocking classes that live outside my project (eg live in the virtualenv). I leave this open, so hopefully someone can show me how to mock these kind of classes.
First of all: make sure you have in Database.py
import MySQLdb.cursors
Otherwise your mentioned error will be raised even if you don't patch anything. If you want double check it add cur=MySQLdb.cursors.DictCursor
at the top of __init__
and remove all patches: you will find the same error raised in the new line. That error will disappear if you load MySQLdb.cursors
somewhere in your context before try to point MySQLdb.cursors.DictCursor
. If you are wondered that you haven't see that error before is because in your production code you import MySQLdb.cursors
before use CanonDatabase()
Now make a test where your constructor will pass and create_connection
evil function don't try to connect anything can be obtained simply by patching just create_connection
and anything else:
class TestSimpler(unittest.TestCase):
@mock.patch('atone_canon.Database.create_connection')
def test_base(self, mock_create_connection):
db = CanonDatabase()
self.assertIsNotNone(db)
Of course you can decorate test class if you want patch create_connection
for every test methods.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.