我正在尝试测试通过lru_cache
记住的方法(因为这是一个昂贵的数据库调用)。与pytest-mock
。
该代码的简化版本是:
class User:
def __init__(self, file):
# load a file
@lru_cache
def get(self, user_id):
# do expensive call
然后我正在测试:
class TestUser:
def test_get_is_called(self, mocker):
data = mocker.ANY
user = User(data)
repository.get(user_id)
open_mock = mocker.patch('builtins.open', mocker.mock_open())
open_mock.assert_called_with('/foo')
但是我遇到以下错误:
TypeError: unhashable type: '_ANY'
之所以会发生这种情况,是因为functools.lru_cache
需要存储的密钥是可散列的,即已实现了方法__hash__
或__cmp__
。
如何在模拟程序中模拟此类方法以使其正常工作?
我尝试过
user.__hash__.return_value = 'foo'
没有运气。
答案 0 :(得分:0)
代替使用mocker.ANY
(打算在断言中用作占位符的对象,该对象等于任何对象),我相信您想使用哨兵对象(例如mocker.sentinel.DATA
) 。
这似乎可以通过快速测试来实现:
from functools import lru_cache
@lru_cache(maxsize=None)
def f(x):
return (x, x)
def test(mocker):
ret = f(mocker.sentinel.DATA)
assert ret == (mocker.sentinel.DATA, mocker.sentinel.DATA)
答案 1 :(得分:0)
对于到达这里试图解决如何测试以lru_cache
或alru_cache
装饰的功能的人们来说,答案是在每次测试之前先clear the cache。
这可以如下进行:
def setup_function():
"""
Avoid the `(a)lru_cache` causing tests with identical parameters to interfere
with one another.
"""
my_cached_function.cache_clear()