如何在Python的数据表中修补装饰器注册的方法?

时间:2016-05-20 22:25:01

标签: python unit-testing decorator python-decorators datashape

我正在使用datashape Python包并使用@datashape.discover.register装饰器注册新类型。我想测试当我在我正在注册的类型的对象上调用datashape.discover时,它会调用正在修饰的函数。我也喜欢用良好的单元测试原理来做这件事,这意味着没有实际执行被装饰的功能,因为它会产生我不想要的副作用。但是,这不起作用。

以下是一些示例代码来说明问题:

myfile.py:

@datashape.discover.register(SomeType)
def discover_some_type(data)
    ...some stuff i don't want done in a unit test...

test_myfile.py:

class TestDiscoverSomeType(unittest.TestCase):
    @patch('myfile.discover_some_type')
    def test_discover_some_type(self, mock_discover_some_type):
        file_to_discover = SomeType()

        datashape.discover(file_to_discover)

        mock_discover_some_type.assert_called_with(file_to_discover)

问题似乎是我想要模拟的函数在测试体中被嘲笑,但是,当它被装饰时(即它被导入时)它没有被嘲笑。 discover.register函数基本上在内部注册要修饰的函数,以便在使用给定类型的参数调用discover()时查找它。不幸的是,它似乎每次都在内部注册真正的函数,而不是我想要的修补版本,所以它总是会调用真正的函数。

有关如何修补正在修饰的函数的任何想法,并声明在调用datashape.discover时调用它?

1 个答案:

答案 0 :(得分:1)

这是我发现的解决方案,只有一点点hacky:

sometype.py:

def discover_some_type(data):
    ...some stuff i don't want done in a unit test...

discovery_channel.py:

import sometype

@datashape.discover.register(SomeType)
def discover_some_type(data):
    return sometype.discover_some_type(data)

test_sometype.py:

class TestDiscoverSomeType(unittest.TestCase):
    @patch('sometype.discover_some_type')
    def test_discover_some_type(self, mock_discover_some_type):
        import discovery_channel

        file_to_discover = SomeType()

        datashape.discover(file_to_discover)

        mock_discover_some_type.assert_called_with(file_to_discover)

关键是你必须在导入具有将修补函数注册到datashape的修饰函数的模块之前修补实际做什么。不幸的是,这意味着你不能让你的装饰功能和在同一个模块中进行发现的功能(所以逻辑上应该在一起的东西现在是分开的)。你在单元测试中有一些hacky import-in-a-function(触发discover.register)。但至少可行