how to mock function call used by imported pypi library in python
我有以下代码,我正在尝试测试:
great_report.py
1 2 3 4 5 6 7 8 9 10 | from retry import retry @retry((ReportNotReadyException), tries=3, delay=10, backoff=3) def get_link(self): report_link = _get_report_link_from_3rd_party(params) if report_link: return report_link else: stats.count("report_not_ready", 1) raise ReportNotReadyException |
我有我的测试功能,它模拟了_get_report_link_from_3rd_party来测试所有内容,但是我不希望这个函数在我运行测试时实际暂停执行。
1 2 3 | @mock.patch('repo.great_report._get_report_link_from_3rd_party', return_value=None) test_get_link_raises_exception(self, mock_get_report_link): self.assertRaises(ReportNotReadyException, get_link) |
我尝试模拟重试参数,但遇到了一些问题,其中get_link一直在重试,导致长的构建时间,而不是仅仅提高异常并继续。 如何在我的测试中模拟@retry调用的参数?
正如这里暗示的那样,一种防止实际睡眠的简单方法是修补
1 | @patch('time.sleep', side_effect = lambda _: None) |
加载模块后无法更改装饰器参数。装饰器装饰原始函数并在模块加载时更改它。
首先,我想鼓励您稍微改变您的设计,使其更易于测试。
如果你提取
如果您不想在类中添加新方法,可以使用配置模块来存储调用
最后一种方法是黑客方式,你用你的版本替换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import unittest from unittest.mock import * from pd import get_link, ReportNotReadyException import retry orig_retry_internal = retry.api.__retry_internal def _force_retry_params(new_tries=-1, new_delay=0, new_max_delay=None, new_backoff=1, new_jitter=0): def my_retry_internals(f, exceptions, tries, delay, max_delay, backoff, jitter, logger): # call original __retry_internal by new parameters return orig_retry_internal(f, exceptions, tries=new_tries, delay=new_delay, max_delay=new_max_delay, backoff=new_backoff, jitter=new_jitter, logger=logger) return my_retry_internals class MyTestCase(unittest.TestCase): @patch("retry.api.__retry_internal", side_effect=_force_retry_params(new_tries=1)) def test_something(self, m_retry): self.assertRaises(ReportNotReadyException, get_link, None) |
恕我直言,你应该使用那个黑客攻击解决方案,只有当你背对墙,你没有机会重新设计你的代码,使其更可测试。内部函数/类/方法可以更改,恕不另行通知,并且您的测试将来很难维护。