user2430771 user2430771 - 4 months ago 24
Python Question

Using python mocking library on sqlalchemy

I'm using sqlalchemy to query my databases for a project. Side-by-side, I'm new to unit testing and I'm trying to learn how can I make unit tests to test my database. I tried to use mocking library to test but so far, it seems to be very difficult.

So I made a piece of code which creates a

object. This object is used to connect to database.

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.exc import OperationalError, ArgumentError

test_db_string = 'postgresql+psycopg2://testdb:hello@localhost/' \
def get_session(database_connection_string):
Base = declarative_base()
engine = create_engine(database_connection_string)
Base.metadata.bind = engine
DBSession = sessionmaker(bind=engine)
session = DBSession()
connection = session.connection()
return session
except OperationalError:
return None
except ArgumentError:
return None

So I made a unit test case for this function:

import mock
import unittest
from mock import sentinel
import get_session

class TestUtilMock(unittest.TestCase):

@mock.patch('app.Utilities.util.create_engine') # mention the whole path
def test_get_session1(self, mock_delarative_base, mock_sessionmaker,
mock_create_engine.return_value = sentinel.engine

As you see in my unit test, I cannot test code in
starting from line
session = DBSession()
. So far after googling, I cannot find out if mock value returned can be also used to mock function calls - something like, I mock
object and verify if I called

Is the above method of writing unit test case the right way? Is there a better method to do this?


First of all you can test session = DBSession() line also by

self.assertEqual(get_session('any_path'), mock_sessionmaker.return_value.return_value)

Morover mock_delarative_base.called is not an assert and cannot fails. Replace it by


General considerations

Write test like these can be very time consuming and make your production code really coupled to test code. It is better to write your own wrapper that present a comfortable interface for your business code and test it by some mocks and real (simple) tests: you should trust sqlalchemy implementation and just test how your wrapper call it

After you can either mock your wrapper by a fake object that you can control or use mocks and check how your code call it but your wrapper will present just some business interface and mock it should be very simple.