我有一个扩展unittest.testcase的基类,我想修补这个基类,这样扩展这个基类的类也将应用修补程序。
代码示例:

@patch("some.core.function", mocked_method)
class BaseTest(unittest.TestCase):
      #methods
      pass

class TestFunctions(BaseTest):
      #methods
      pass

直接修补TestFunctions类是有效的,但是修补basetest类不会改变some.core.function中的功能。

最佳答案

这里可能需要一个元类:元类只定义了类的创建方式。
默认情况下,所有类都是使用python的内置类创建的。

>>> class Foo:
...     pass
...
>>> type(Foo)
<class 'type'>
>>> isinstance(Foo, type)
True

所以类实际上是type的实例。
现在,我们可以子类type来创建自定义元类(创建类的类):
class PatchMeta(type):
    """A metaclass to patch all inherited classes."""

我们需要控制类的创建,所以我们要重写这里的type并在所有新实例上使用type.__new__修饰器:
class PatchMeta(type):
    """A metaclass to patch all inherited classes."""

    def __new__(meta, name, bases, attrs):
        cls = type.__new__(meta, name, bases, attrs)
        cls = patch("some.core.function", mocked_method)(cls)
        return cls

现在只需使用以下命令设置元类:
class BaseTest(unittest.TestCase):
    __metaclass__ = PatchMeta
    # methods

问题是这一行:
cls = patch("some.core.function", mocked_method)(cls)

所以现在我们总是用参数来修饰。
相反,您可以使它使用类的属性,例如:
cls = patch(*cls.patch_args)(cls)

然后将patch添加到类中:
class BaseTest(unittest.TestCase):
    __metaclass__ = PatchMeta
    patch_args = ("some.core.function", mocked_method)

编辑:正如注释中提到的@mgilson,在适当的位置修改类的方法,而不是返回新的类。因此,我们可以将__metaclass__ = PatchMeta替换为"some.core.function"
class PatchMeta(type):
    """A metaclass to patch all inherited classes."""

    def __init__(cls, *args, **kwargs):
        super(PatchMeta, self).__init__(*args, **kwargs)
        patch(*cls.patch_args)(cls)

它绝对是干净的。

关于python - 继承一个修补过的类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32981141/

10-11 03:56