I'm new to Mock testing. For learning purposes, I'm trying to simulate the status check whether the database connection established or not and no of times the Handler is trying to perform database connect operation.
class Handler:
def is_connected(self):
# return true if connected to the backend database
pass
class Backend:
def initConnection(self):
handlr = Handler()
while(True):
is_connected = handlr.is_connected()
print(is_connected)
if(is_connected):
break
class TestBackendConnection(TestCase):
def test_connection_waiting(self):
"""Test that the backend waits for connection untill the handler connects"""
with patch('side_eff.Handler.is_connected') as isconn:
bknd = Backend()
isconn.side_effect = [False] * 4 + [True]
# print(tryCon()) => False
# print(tryCon()) => False
# print(tryCon()) => False
# print(tryCon()) => False
# print(tryCon()) => True
bknd.initConnection()
self.assertEqual(isconn.call_count, 5)
I'm patching is_connected method of Handler class with side_effect so as to prepare a test case such that for the first four attempts connection is not established and on the fifth attempt connection is established.
Though I mocked the method, the original method is being called.
My Assumption:
On initializing mock behavior to any target, any call made from a newly initialized object to such target mimics the mock behavior defined while patching.
Here is the unit test solution:
side_eff.py
:
class Handler:
def is_connected(self):
pass
class Backend:
def initConnection(self):
handlr = Handler()
while(True):
is_connected = handlr.is_connected()
print(is_connected)
if(is_connected):
break
test_side_eff.py
:
import unittest
from side_eff import Backend
from unittest.mock import patch
class TestBackendConnection(unittest.TestCase):
def test_connection_waiting(self):
"""Test that the backend waits for connection untill the handler connects"""
with patch('side_eff.Handler') as MockHandler:
handlerInstance = MockHandler.return_value
handlerInstance.is_connected.side_effect = [False] * 4 + [True]
bknd = Backend()
bknd.initConnection()
self.assertEqual(handlerInstance.is_connected.call_count, 5)
if __name__ == '__main__':
unittest.main()
Unit test result with coverage report:
(venv) ☁ python-codelab [master] ⚡ coverage run /Users/ldu020/workspace/github.com/mrdulin/python-codelab/src/stackoverflow/59137518/test_side_eff.py
False
False
False
False
True
.
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK
(venv) ☁ python-codelab [master] ⚡ coverage report -m
Name Stmts Miss Cover Missing
---------------------------------------------------------------------------
src/stackoverflow/59137518/side_eff.py 11 1 91% 4
src/stackoverflow/59137518/test_side_eff.py 13 0 100%
---------------------------------------------------------------------------
TOTAL 24 1 96%
Source code: https://github.com/mrdulin/python-codelab/tree/master/src/stackoverflow/59137518