def test_prepare_qs_stmt_force(self):
        """
        Given an ORM statement has already been prepared in the database
        When  prepare_qs_stmt is called for the same function
        And   force is False
        Then  a StatementAlreadyPreparedException error will be raised
        ---
        Given an ORM statement has already been prepared in the database
        When  prepare_qs_stmt is called for the same function
        And   force is True
        Then  the existing statement will be deallocated
        And   the statement will be re-prepared
        """
        psc = PreparedStatementController()
        psc.register_qs("gen_qs", lambda: Species.prepare.all())

        with patch.object(PreparedORMStatement, "prepare", return_value=None):
            psc.prepare_qs_stmt("gen_qs", force=False)
            self.assertTrue("gen_qs" in psc.prepared_statements)

        with self.assertRaises(StatementAlreadyPreparedException):
            psc.prepare_qs_stmt("gen_qs", force=False)

        with patch.object(PreparedORMStatement, "prepare",
                          return_value=None) as mock_prepare:
            with patch.object(PreparedORMStatement,
                              "deallocate",
                              return_value=None) as mock_deallocate:
                psc.prepare_qs_stmt("gen_qs", force=True)
        mock_deallocate.assert_called_once()
        mock_prepare.assert_called_once()
    def test_register_qs(self):
        """
        Given a function that returns an ORM query
        When  register_qs is called with that function as one of the arguments
        Then  that function should be added to the qs_generating_functions dict
        """
        def gen_qs():
            pass

        psc = PreparedStatementController()
        psc.register_qs("gen_qs", gen_qs)
        self.assertFalse("gen_qs" in psc.sql_generating_functions)
        self.assertTrue("gen_qs" in psc.qs_generating_functions)
        self.assertTrue(psc.qs_generating_functions["gen_qs"] is gen_qs)
    def test_prepare_qs_stmt(self):
        """
        Given a function that generates an ORM query has been registered with the PreparedStatementController
        When  prepare_qs_stmt is called
        Then  a PreparedORMStatement object should be created
        And   the PreparedORMStatement should be added to the prepared_statements dict
        And   the SQL will be preapred in the database
        """
        psc = PreparedStatementController()
        psc.register_qs("gen_qs", lambda: Species.prepare.all())

        with patch.object(PreparedORMStatement, "prepare",
                          return_value=None) as mock_prepare:
            psc.prepare_qs_stmt("gen_qs", force=False)
            self.assertTrue("gen_qs" in psc.prepared_statements)
            self.assertTrue(
                isinstance(psc.prepared_statements["gen_qs"],
                           PreparedORMStatement))
        mock_prepare.assert_called_once()
    def test_prepare_all(self):
        """
        Given a set of sql and qs generating functions that have been registered with the PreparedStatementController
        When  prepare_all() is called
        Then  prepare_sql_stmt and prepare_qs_stmt should be called for each registered function as appropriate
        """
        psc = PreparedStatementController()
        psc.register_sql("gen_sql1", lambda: None)
        psc.register_sql("gen_sql2", lambda: None)
        psc.register_sql("gen_sql3", lambda: None)
        psc.register_qs("gen_qs1", lambda: Species.prepare.all())
        psc.register_qs("gen_qs2", lambda: Species.prepare.all())

        with patch.object(PreparedORMStatement, "prepare",
                          return_value=None) as mock_orm_prepare:
            with patch.object(PreparedStatement, "prepare",
                              return_value=None) as mock_sql_prepare:
                psc.prepare_all()
        self.assertEqual(mock_sql_prepare.call_count, 3)
        self.assertEqual(mock_orm_prepare.call_count, 2)