如何测试被cached装饰的方法仅调用一次内部方法?
问题描述
我使用@cached装饰器(缓存为TTLCache(maxsize=1024, ttl=600))装饰了get_data方法,该方法内部会调用get_result获取结果。编写的测试用例如下:
from cachetools import cached, TTLCache class MyClass: @cached(cache=TTLCache(maxsize=1024, ttl=600)) def get_data(self, key): result = self.get_result(key) return result def get_result(self, key): # 实际业务逻辑 pass def test_get_data(self): my_class = MyClass() my_class.get_data.return_value = 'text' my_class.get_data('id') my_class.get_data('id') my_class.get_result.assert_called_once()
执行测试时触发断言错误:
E AssertionError: Expected 'get_result' to have been called once. Called 2 times.
请问如何正确测试该内部方法仅被调用一次?
解决方案
你的测试逻辑存在核心问题:直接给my_class.get_data.return_value赋值,相当于完全Mock了get_data方法,直接绕过了原方法的缓存逻辑和内部调用逻辑。这时候两次调用get_data根本不会触发缓存机制,原方法的逻辑反而被执行了两次,导致get_result被调用两次。
正确的测试方式是Mockget_result方法,让它返回预期值,然后调用get_data两次,验证缓存生效(即get_result仅被调用一次)。修正后的测试代码如下:
基于unittest框架的写法
from unittest.mock import patch import unittest class TestMyClass(unittest.TestCase): def test_get_data(self): my_class = MyClass() # Mock get_result方法,指定返回值 with patch.object(my_class, 'get_result', return_value='text') as mock_get_result: # 第一次调用,触发get_result result1 = my_class.get_data('id') # 第二次调用,应该走缓存,不触发get_result result2 = my_class.get_data('id') # 验证返回值符合预期 self.assertEqual(result1, 'text') self.assertEqual(result2, 'text') # 验证get_result仅被调用一次,且参数正确 mock_get_result.assert_called_once_with('id')
基于pytest框架的写法
from unittest.mock import patch def test_get_data(): my_class = MyClass() with patch.object(my_class, 'get_result', return_value='text') as mock_get_result: result1 = my_class.get_data('id') result2 = my_class.get_data('id') assert result1 == 'text' assert result2 == 'text' mock_get_result.assert_called_once_with('id')
核心思路:不要Mock被缓存的get_data方法,而是Mock它依赖的get_result方法,让原方法的缓存逻辑正常运行,从而验证缓存是否生效(内部方法是否仅被调用一次)。
内容的提问来源于stack exchange,提问作者Observer
相关产品推荐
相关产品推荐

