0

I have the following unittest which needs to test the flask route.

@unittest.mock.patch('flask_login.utils._get_user')
@unittest.mock.patch('flask_sqlalchemy.SQLAlchemy')
def test_attendances_management(self, SQLAlchemy, current_user):

    user = MagicMock()

    sqlalchemy = SQLAlchemy()
    sqlalchemy.engine.return_value = MagicMock()

    sqlalchemy.engine.raw_connection.return_value = MagicMock()

    sqlalchemy.engine.raw_connection.cursor.return_value = MagicMock()

    sqlalchemy.engine.raw_connection.cursor.callproc("get_project_members", [3, 9, 2020]).return_value = ((1, 3, 4),)

    current_user.return_value = user
    current_user.return_value.role.name = 'Administrator'
    current_user.return_value.id = 1

    response = self.client.get('attendances/management/3/2020/11')
    self.assertEqual(response.status_code, 200)

Everything goes fine (mocking db engine, raw_connection, and cursor), but I have a problem that get_project_members doesn't exist. Which part of flask-sqlalchemy or MySQLdb library I need to mock in order to fake that some procedure actually exists because I use flask-testing to create for example some table `ExampleTable.table.create(db.session.bind), and I don't know how to create a stored procedure or how to use mock to emulate that procedure.

Exception log:

    File "C\:my_app\app\attendances\views.py", line 169, in management
    cursor.callproc("get_project_members", [project_id, month, year])
  File "c:\my_app\flaskvenv\lib\site-packages\MySQLdb\cursors.py", line 365, in callproc
    self._query(q)
  File "c:\my_app\flaskvenv\lib\site-packages\MySQLdb\cursors.py", line 411, in _query
    rowcount = self._do_query(q)
  File "c:\my_app\flaskvenv\lib\site-packages\MySQLdb\cursors.py", line 374, in _do_query
    db.query(q)
  File "c:\my_app\flaskvenv\lib\site-packages\MySQLdb\connections.py", line 277, in query
    _mysql.connection.query(self, query)
_mysql_exceptions.OperationalError: (1305, 'PROCEDURE my_app_test_db.get_project_members does not exist')
Matija Lukic
  • 599
  • 8
  • 28

1 Answers1

0

I've just solved this by using cursor.execute method which use raw query to create MySQL procedure. Also, I already have db as instance of SQLAlchemy, so I don't need to mock already defined connection.

    @unittest.mock.patch('flask_login.utils._get_user')
    def test_attendances_management(self, current_user):

        user = MagicMock()
        q = "CREATE PROCEDURE `get_project_members` (IN `project_id` INT, IN `month` INT, IN `year` INT) BEGIN END"
        connection = db.engine.raw_connection()
        cursor = connection.cursor()
        cursor.execute(q)

        current_user.return_value = user
        current_user.return_value.role.name = 'Administrator'
        current_user.return_value.id = 1

        response = self.client.get('attendances/management/3/2020/11')
        self.assertEqual(response.status_code, 200)

Similar answer: Creating Stored Procedures with SQLAlchemy

Matija Lukic
  • 599
  • 8
  • 28