Python 在导入类之前对其进行模拟

Python 在导入类之前对其进行模拟,python,mocking,python-unittest,Python,Mocking,Python Unittest,我试图模拟父类中的一个方法,该方法在任何类方法之外声明。问题是,我不知道如何在父类中实例化LoggerUtils类。由于实现的巨大规模和重构的成本,将其放在一个_uinit__;中不是一个选项 在导入测试类之前,有没有办法模拟父类 导入类时,至少要在加载之前模拟该方法 有没有办法解决导入时加载非惰性方法的问题 我尝试了懒惰的加载方法,但我就是没有让它工作;使用mock库修补所有方法,但方法总是在我可以模拟任何东西之前加载。下面我有一个模拟尝试的例子,但总是调用LoggerUtils 父类:

我试图模拟父类中的一个方法,该方法在任何类方法之外声明。问题是,我不知道如何在父类中实例化LoggerUtils类。由于实现的巨大规模和重构的成本,将其放在一个_uinit__;中不是一个选项

  • 在导入测试类之前,有没有办法模拟父类

  • 导入类时,至少要在加载之前模拟该方法

  • 有没有办法解决导入时加载非惰性方法的问题

我尝试了懒惰的加载方法,但我就是没有让它工作;使用mock库修补所有方法,但方法总是在我可以模拟任何东西之前加载。下面我有一个模拟尝试的例子,但总是调用LoggerUtils

父类:

抽象api.py

class AbstractApi:

    logger = LoggerUtils.get_logger('AbstractApi')
    def update(self):
        <code>


要测试的类:

api\u映射\u资产\u类型.py

from abstract_api import AbstractApi


class ApiMapAssetType(AbstractApi):
    def update(self):
        <code>

from unittest import TestCase
from mock imort patch
from api_map_asset_type import ApiMapAssetType


class TestApiMapAssetType(TestCase):

    @patch('api_map_asset_type.AbstractApi.LoggerUtils')
    @patch('api_map_asset_type.AbstractApi')
    def setUp(self, mock2_abstract_loger, mock_3):
        self.asset_api = ApiMapAssetType()

    @patch('AbstractApi.update')
    def test_update(self, mock_parent_update):

        mock_orm = MagicMock()
        self.asset_api.update()
        mock_parent_update.assert_called_with()
from undetermined_project_library.LoggerUtils import LoggerUtils
with patch.object(LoggerUtils, 'get_logger') as mock_logger:

    from unittest import TestCase
    from mock imort patch
    from api_map_asset_type import ApiMapAssetType


    class TestApiMapAssetType(TestCase):

    def setUp(self):
            self.asset_api = ApiMapAssetType()

        @patch('AbstractApi.update')
        def test_update(self, mock_parent_update):

            mock_orm = MagicMock()
            self.asset_api.update()
            mock_parent_update.assert_called_with()

测试等级:

测试\ api \映射\资产\类型.py

from abstract_api import AbstractApi


class ApiMapAssetType(AbstractApi):
    def update(self):
        <code>

from unittest import TestCase
from mock imort patch
from api_map_asset_type import ApiMapAssetType


class TestApiMapAssetType(TestCase):

    @patch('api_map_asset_type.AbstractApi.LoggerUtils')
    @patch('api_map_asset_type.AbstractApi')
    def setUp(self, mock2_abstract_loger, mock_3):
        self.asset_api = ApiMapAssetType()

    @patch('AbstractApi.update')
    def test_update(self, mock_parent_update):

        mock_orm = MagicMock()
        self.asset_api.update()
        mock_parent_update.assert_called_with()
from undetermined_project_library.LoggerUtils import LoggerUtils
with patch.object(LoggerUtils, 'get_logger') as mock_logger:

    from unittest import TestCase
    from mock imort patch
    from api_map_asset_type import ApiMapAssetType


    class TestApiMapAssetType(TestCase):

    def setUp(self):
            self.asset_api = ApiMapAssetType()

        @patch('AbstractApi.update')
        def test_update(self, mock_parent_update):

            mock_orm = MagicMock()
            self.asset_api.update()
            mock_parent_update.assert_called_with()


已编辑

这是我找到的唯一解决方案,因为我无法在导入之前模拟类属性中的父类或模拟方法,所以我决定在导入之前模拟整个测试,但我认为这不是一个最佳或干净的解决方案:

测试等级:

测试\ api \映射\资产\类型.py

from abstract_api import AbstractApi


class ApiMapAssetType(AbstractApi):
    def update(self):
        <code>

from unittest import TestCase
from mock imort patch
from api_map_asset_type import ApiMapAssetType


class TestApiMapAssetType(TestCase):

    @patch('api_map_asset_type.AbstractApi.LoggerUtils')
    @patch('api_map_asset_type.AbstractApi')
    def setUp(self, mock2_abstract_loger, mock_3):
        self.asset_api = ApiMapAssetType()

    @patch('AbstractApi.update')
    def test_update(self, mock_parent_update):

        mock_orm = MagicMock()
        self.asset_api.update()
        mock_parent_update.assert_called_with()
from undetermined_project_library.LoggerUtils import LoggerUtils
with patch.object(LoggerUtils, 'get_logger') as mock_logger:

    from unittest import TestCase
    from mock imort patch
    from api_map_asset_type import ApiMapAssetType


    class TestApiMapAssetType(TestCase):

    def setUp(self):
            self.asset_api = ApiMapAssetType()

        @patch('AbstractApi.update')
        def test_update(self, mock_parent_update):

            mock_orm = MagicMock()
            self.asset_api.update()
            mock_parent_update.assert_called_with()


如果我了解您的模块布局,这应该可以:

class TestApiMapAssetType(TestCase):

    @patch('undetermined_project_library.LoggerUtils')
    def setUp(self, mock_abstract_logger):
        self.asset_api = ApiMapAssetType()

    @patch('api_map_asset_type.ApiMapAssetType.update')
    def test_update(self, mock_parent_update):
        self.asset_api.update()
        mock_parent_update.assert_called_with()
请注意以下几点:

  • 您必须从它们定义的库中模拟
    LoggerUtils
    ;您使用了
    AbstractApi.LoggerUtils
    ,这是不正确的,因为
    LoggerUtils
    不属于
    AbstractApi
  • 我删除了
    AbstractApi
    的模拟-至少在这个方面你不需要它
  • update
    为实际调用的方法进行了修补-如果调用基本实现,则使用基类方法可能有意义(不知道是否这样做)
  • 我猜你的一些模块布局-你可能需要调整它

我真的不明白您想做什么,但是
补丁
调用看起来是错误的:您补丁了
api\u map\u asset\u type.AbstractApi
,然后是
AbstractApi.LoggerUtils
。我尝试了不同的组合来修补这些类,但任何组合都有效。问题是,由于有人在类属性中调用了de Logger类,所以在导入时会调用此方法,因为Python不执行惰性导入。在导入之前,我试图找到一种模拟此方法的方法。因此,在测试中,您在
setUp
中调用
apimapasettype()
,但您没有导入它-因此我猜您没有显示完整的代码。你们在那里做本地进口吗?请显示一个。好吧,我放置了导入,我尝试将它放在补丁之前/之后,或者用sys.modules加载来伪装它。我还尝试了LazyLoad函数。我仍然认为
LoggerUtils
的修补程序不正确-请确保以与访问它相同的方式进行修补-可能是
api\u map\u asset\u type.AbstractApi.LoggerUtils
,或者
AbstractApi
所在的相应模块。