Unittest 模拟了 class 的方法未被调用

Unittest mocked class's method not being called

我是模拟测试的新手。出于学习目的,我尝试模拟状态检查是否建立了数据库连接,以及 Handler 尝试执行数据库连接操作的次数。

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)

我正在用 side_effect 修补处理程序 class 的 is_connected 方法,以便准备一个测试用例 前四次尝试连接未建立,第五次尝试连接建立

虽然我mock了方法,但是调用的还是原来的方法

我的假设:

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.

单元测试解决方案如下:

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()

带有覆盖率报告的单元测试结果:

(venv) ☁  python-codelab [master] ⚡  coverage run /Users/ldu020/workspace/github.com/mrdulin/python-codelab/src/Whosebug/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/Whosebug/59137518/side_eff.py           11      1    91%   4
src/Whosebug/59137518/test_side_eff.py      13      0   100%
---------------------------------------------------------------------------
TOTAL                                            24      1    96%

源代码:https://github.com/mrdulin/python-codelab/tree/master/src/Whosebug/59137518