Skip to main content
 首页 » 编程设计

Python 模拟 : How to test the number of calls on a recursive function

2025年05月04日40mq0036

我在名为 test_module 的模块中有一个递归函数

import requests     
 
def send_msg(msg, retries=0): 
    try: 
        # send the message here, e.g. a http request 
        response = requests.get("http://www.doesnotexist98734.com") 
        # if url does not exist raise an exception 
    except Exception as e: 
        if retries == 0: 
            raise e 
        else: 
            return send_msg(msg, retries=retries-1) 

我的问题是如何编写一个单元测试来检查 send_msg 函数在我设置 retries = n 时被调用了 n 次。我正在玩模拟模块(我使用的是 python 2.7),我想我想要这样的东西,

import mock, unittest 
 
class MyUnitTest(unittest.TestCase): 
 
    @mock.patch('test_module.send_msg') 
    def test_send_msg_tries_n_times(self, mock_send_msg): 
        with self.assertRaises(Exception): 
            mock_send_msg("hello", retries=3) 
        self.assertEqual(mock_send_msg.call_count, 4) # initial call + 3 retries 

然而,由于我已经模拟了该函数,它不会调用真正的函数,所以我不会得到异常,也不会递归地调用自己...

请您参考如下方法:

您不能模拟被测函数。您想要测试预期结果,而不是函数是否正确使用了递归。

模拟 request.get() 调用,让它总是产生异常。然后计算你的模拟被调用的频率。

@mock.patch('requests.get') 
def test_send_msg_tries_n_times(self, req_get_mock): 
    req_get_mock.side_effect = Exception 
    with self.assertRaises(Exception): 
        send_msg("hello", retries=3) 
    self.assertEqual(req_get_mock.call_count, 4)  # 1 initial call + 3 retries 

如果将来您想避免使用递归并希望使用迭代,您的测试仍然可以工作,因为它验证的是行为,而不是特定的实现。您可以安全地重构被测函数。