Reputation: 577
I have the following function that yields a pyodbc.connect()
object to use with a with
statement:
from contextlib import contextmanager
import pyodbc
@contextmanager
def get_db_connection(conn_string, **kwargs):
try:
conn = pyodbc.connect(conn_string, **kwargs)
yield conn
except Exception as connection_error:
raise ValueError('Could not connect to db.', connection_error) from None
finally:
conn.close()
I'd like to write unit tests for this function to test that a connection can be opened, closed, and when an error occurs, a ValueError
is raised. I have:
from unittest.mock import Mock, patch
from db.query import get_db_connection
@patch('db.query.pyodbc.connect')
def test_get_db_connection(self, mock_connect):
conn_string = Mock()
with get_db_connection(conn_string) as conn:
pass
# print(conn) is acceptable here and prints:
# <MagicMock name='connect()' id='2595126451264'>
mock_connect.assert_called_once()
mock_connect.side_effect = Exception()
def _t():
with get_db_connection(conn_string) as conn:
pass
self.assertRaises(UnboundLocalError, _t)
Everything here runs and passes, but I've noticed the conn
is available after the with
statement scope should be closed.
How do I write a unit test for get_db_connection()
using mock
so that the conn
variables behave as I'd expect them? Or is there another way to sufficiently unit test it?
Upvotes: 3
Views: 3149
Reputation: 577
Use
conn.close.assert_not_called()
to check that the connection is opened in the first with
block.conn.close.assert_called_once()
to check that the connection is closed after the first with
block.try
block - UnboundLocalError: local variable 'conn' referenced before assignmentUpvotes: 2