Home > Blockchain >  how to write pytest for pymssql?
how to write pytest for pymssql?

Time:11-25

I am trying to write pytest 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.

//fetch.py

import pymssql

def cur_fetch(query):
    with pymssql.connect('host', 'username', 'password') as conn:
        with conn.cursor(as_dict=True) as cursor:
            cursor.execute(query)
            response = cursor.fetchall()
    return response

//test_fetch.py

import mock
from unittest.mock import MagicMock, patch
from .fetch import cur_fetch
def test_cur_fetch():
    with patch('fetch.pymssql', autospec=True) as mock_pymssql:
        mock_cursor = mock.MagicMock()
        test_data = [{'password': 'secret', 'id': 1}]
        mock_cursor.fetchall.return_value = MagicMock(return_value=test_data)
        mock_pymssql.connect.return_value.cursor.return_value.__enter__.return_value = mock_cursor
        x = cur_fetch({})
        assert x == None

The result is:

AssertionError: assert <MagicMock name='pymssql.connect().__enter__().cursor().__enter__().fetchall()' id='2250972950288'> == None

Please help.

CodePudding user response:

Trying to mock out a module is difficult. Mocking a method call is simple. Rewrite your test like this:

import unittest.mock as mock
import fetch

def test_cur_tech():
    with mock.patch('fetch.pymssql.connect') as mock_connect:
        mock_conn = mock.MagicMock()
        mock_cursor = mock.MagicMock()

        mock_connect.return_value.__enter__.return_value = mock_conn
        mock_conn.cursor.return_value.__enter__.return_value = mock_cursor
        mock_cursor.fetchall.return_value = [{}]

        res = fetch.cur_fetch('select * from table')
        assert mock_cursor.execute.call_args.args[0] == 'select * from table'
        assert res == [{}]

In the above code we're explicitly mocking pymyssql.connect, and providing appropriate fake context managers to make the code in cur_fetch happy.

You could simplify things a bit if cur_fetch received the connection as an argument, rather than calling pymssql.connect itself.

  • Related