3

I have the following code setup, and I have a test case to test the Db.__init__ already, how do I test the __del__? Can you provide an example?

import psycopg2


class Db(object):
    def __init__(self):
        import app
        conn_string = "host='{}' port='{}' dbname='{}' user='{}' password='{}'".format(app.app.config['DB_HOST'], \
                      app.app.config['DB_PORT'], app.app.config['DB_NAME'], app.app.config['DB_USER'], \
                      app.app.config['DB_PASSWORD'])
        self.conn = psycopg2.connect(conn_string)

    def __del__(self):
        self.conn.close()

Test Case

@ddt
class TestDB(unittest.TestCase):
    @patch('psycopg2.connect')
    def test_db_constructor(self, mock_psycopg2_connect):
        mock_psycopg2_connect.returned_value = True
        db = Db()

        self.assertTrue(db.conn)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
user1187968
  • 7,154
  • 16
  • 81
  • 152
  • You have a typo, it should be `mock_psycopg2_connect.return_value`. – Martijn Pieters May 17 '17 at 18:33
  • You should not be using `__del__` (see [this answer](http://stackoverflow.com/questions/1481488/what-is-the-del-method-how-to-call-it/2452895#2452895)). Maybe you could solve your problem with a [`with` statement](http://effbot.org/zone/python-with-statement.htm). – Solomon Slow May 17 '17 at 19:17

1 Answers1

2

Just call the method directly, having mocked out self.conn via the __init__ method:

@patch('psycopg2.connect')
def test_db_destructor(self, mock_psycopg2_connect):
    db = Db()
    mock_conn = mock_psycopg2_connect.return_value
    close = mock_conn.close

    db.__del__()
    close.assert_called_once()

Your original test has a flaw; you misspelled return_value, so your mock connect never returns True; it returns a new mock object. That mock object just happens to have a true value:

>>> from unittest.mock import MagicMock
>>> mock = MagicMock()
>>> mock.connect()
<MagicMock name='mock.connect()' id='4536051752'>
>>> bool(mock.connect())
True

To properly test that the connect() method return value is stored in db.conn, test if that attribute is the exact same object as what the mock returns:

@patch('psycopg2.connect')
def test_db_constructor(self, mock_psycopg2_connect):
    mock_conn = mock_psycopg2_connect.return_value

    db = Db()
    self.assertTrue(db.conn is mock_conn)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343