2

I am trying to write unit test case to test the following method by mocking the database. How to mock the database connection without actually connecting to the real database server.I tried with sample test case. I am not sure if that is right way to do it. Please correct me if I am wrong.

//MySQL.py
    class MySQL():

        retry_interval = 20000 

        def link(self, server,port):
            try:
                return pymysql.connect(server, username='name', passwd='pwd', db='demo', int(port))
                sys.stdout.write('Connected to database at {}:{}\n'.format(server,port))
            except:
                sys.stderr.write('Retry database connection in {} ms...\n'.format(self.retry_interval))
                sleep(self.retry_interval/1000.0)
                continue

//test.py
from unittest.mock import Mock, MagicMock
from unittest.mock import patch
import MySQL

   @patch('MySQL.pymysql')
    def testLink(self, mysql_mock):
        mock_cursor = Mock.MagicMock()
        mysql_mock.connect.return_value.cursor.return_value.__enter__.return_value = mock_cursor
2
  • The limits of a unittest end where the edge of your code is reached. In your case pymysql.connect is out of the scope of a unittest and should be mocked. What you should test is if the mock is called properly. Commented Nov 6, 2017 at 10:48
  • @KlausD. okay Thanks. will try Commented Nov 6, 2017 at 11:13

1 Answer 1

4

The only useful thing you can really test in MySQL.pymysql is the connect method, so you might as well patch that directly:

//test.py
from unittest.mock import Mock, MagicMock
from unittest.mock import patch, call
import MySQL

@patch('MySQL.pymysql.connect')
def testLink(self, connect_mock):
    # You can configure a return value for the connection if you need to...
    connect_mock.return_value = MagicMock(name='connection_return', return_value=...)

    # You can now test that your connection is being called...
    self.assertEqual(1, connect_mock.call_count)

    # You can also check the call parameters...
    self.assertEqual(connect_mock.call_args_list[0], call(server, username='name', passwd='pwd',...))
Sign up to request clarification or add additional context in comments.

7 Comments

Hi Thanks for the help. I tried the same way as shown in the example code. But I am confused If i should mock the function "link" or only the call to "pymysql.connect" ?
@patch('MySQL.pymysql.connect') gives unused import and SyntaxError: non-keyword arg after keyword arg
Hi. I don't think you need to mock the link function to test the code you've given. You would mock the pymysql.connect function and then your test would call the link function which would return the mocked connect object.
The SyntaxError is most likely caused by the ordering of your arguments in your method declaration (see here for details). Try rearranging your pymysql.connect arguments so that the named arguments (usernam, password, db) come after the positional arguments (server and port).
Okay Thanks. I fixed that Syntax error. But I always get this error ImportError: No module named pymysql. I have installed the pymysql. Is this the right way to refer in patch @patch('MySQL.pymysql.connect')?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.