禁用 functools.cache 进行测试

Ita*_*ayB 3 python mocking pytest python-3.x python-decorators

我@cache在我的方法中使用装饰器:

class Configuration:

    @classmethod
    @property
    @cache
    def whitelist_sections(cls) -> Set[int]:
        whitelist_sections: Set[int] = set()
        whitelist: str = os.getenv("WHITELIST_SECTIONS", "")
        try:
            whitelist_sections = eval("{" + whitelist + "}")
        except ValueError:
            return whitelist_sections
        return whitelist_sections
Run Code Online (Sandbox Code Playgroud)

我想测试上面的方法,这是我的努力:

def test_whitelist_sections():
    section_id = 8765432
    env_var_mock = mock.patch.dict(os.environ, {"WHITELIST_SECTIONS": str(section_id)})
    env_var_mock.start()
    whitelist_sections = Configuration.whitelist_sections
    env_var_mock.stop()
    assert whitelist_sections == {section_id}


def test_whitelist_multiple_sections():
    section_id_1 = 8765432
    section_id_2 = 1234567
    env_var_mock = mock.patch.dict(os.environ, {"WHITELIST_SECTIONS": f"{section_id_1},{section_id_2}"})
    env_var_mock.start()
    whitelist_sections = Configuration.whitelist_sections
    env_var_mock.stop()
    assert whitelist_sections == {section_id_1, section_id_2}


def test_whitelist_sections_empty():
    env_var_mock = mock.patch.dict(os.environ, {"WHITELIST_SECTIONS": ""})
    env_var_mock.start()
    whitelist_sections = Configuration.whitelist_sections
    env_var_mock.stop()
    assert whitelist_sections == {}

Run Code Online (Sandbox Code Playgroud)

问题是缓存不允许我测试不同的场景。我如何嘲笑@cache装饰者?

我尝试了这种方法,但没有成功:

cache_mock = mock.patch("functools.cache", lambda func: func)
Run Code Online (Sandbox Code Playgroud)

编辑:尝试了这种方法:

def mock_cache(function):
    return function()


def test_whitelist_sections():
    section_id = 8765432
    env_var_mock = mock.patch.dict(os.environ, {"WHITELIST_SECTIONS": str(section_id)})
    env_var_mock.start()
    cache_mock = mock.patch("my_module.configuration.cache", mock_cache)
    cache_mock.start()
    whitelist_sections = Configuration.whitelist_sections
    cache_mock.stop()
    env_var_mock.stop()
    assert whitelist_sections == {section_id}
Run Code Online (Sandbox Code Playgroud)

在调试模式下运行,我可以看到装饰器已被替换,mock_cache但一起运行pytest仍然会产生两个(免费)测试相同的错误 - 只有第一个测试有效

EDIT2:请注意,这是一个静态方法(@classmethod)

小智 6

装饰器向它装饰的函数@cache添加一个cache_clear属性,因此最简单的方法是在调用缓存函数之前将此行添加到测试中:

whitelist_sections.cache_clear()
Run Code Online (Sandbox Code Playgroud)

如果您发现自己在很多测试中都这样做,您可以制作一个自动使用的固定装置,它始终会清除此缓存。

@pytest.fixture(autouse=True)
def clear_caches():
    whitelist_sections.cache_clear()
    other_cached_function.cache_clear()
Run Code Online (Sandbox Code Playgroud)

将其添加到您的测试文件或适当位置的conftest.py文件中,以递归地影响该模块中的所有测试。