具有side_effect和autospec的Python模拟属性

问题描述

在模拟具有side_effect的实例属性时需要一些帮助,以便将该实例作为参数传递给side_effect。

import unittest
from unittest.mock import patch,PropertyMock

class Host:
    
    def __init__(self,name):
        self.name = name
    
    @property
    def api_version(self):
        return "2.0"
    
    def fetch_app(self):
        if self.api_version == "1.0":
            return "app1"
        return "app"

def _get_api_version(host: Host):
    print("_get_api_version is called")
    if host.name == "host-11":
        return "1.0"
    return "2.0"

class HostMock(unittest.TestCase):
    
    """
    # fails rightly with TypeError: _get_api_version() missing 1 required positional argument: 'host' 
    def test_fetch_id_A(self):
        mock_host = Host("host-99")
        with patch("__main__.Host.api_version",new_callable=PropertyMock,side_effect=_get_api_version):
            self.assertEqual(mock_host.fetch_app(),"app")
    """
    
    # But this doesn't even call _get_api_version
    def test_fetch_id_B(self):
        mock_host = Host("host-11")
        with patch("__main__.Host.api_version",side_effect=_get_api_version,autospec=True):
            self.assertEqual(mock_host.fetch_app(),"app1")

if __name__ == "__main__":
    unittest.main()

如果使用api_version的常规方法,而不是将其设为属性,则test_fetch_id_B通过。但是我不想用普通方法替换属性。这个想法是根据实例的某些属性返回不同的属性值。

任何提示将不胜感激。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)