繁体   English   中英

将闭包传递给函数中的FunctionType

[英]Pass closure to FunctionType in function

我有这样的代码:

class A():
    def __init__(self, a):
        self.a = a

    def outer_method(self):
        def inner_method():
            return self.a +1
        return inner_method()

我想为inner_method编写测试。 为此,我正在使用这样的代码:

def find_nested_func(parent, child_name):
    """ 
       Return the function named <child_name> that is defined inside
        a <parent> function
        Returns None if nonexistent
    """
    consts = parent.__code__.co_consts
    item = list(filter(lambda x:isinstance(x, CodeType) and x.co_name==child_name, consts ))[0]
    return FunctionType(item, globals())

find_nested_func(A().outer_method, 'inner_method')调用它,但是在调用'FunctionType'时失败,因为无法创建函数,因为'self.a'在函数停止成为内部函数时就停止存在。 我知道构造FunctionType可以将可以解决此问题的闭包作为参数来接受,但是我不知道如何使用它。 我该如何通过?

它给出的错误是下一个错误:

    return FunctionType(item, globals())
TypeError: arg 5 (closure) must be tuple

为什么要尝试测试inner_method 在大多数情况下,您应该只测试公共API的一部分。 outer_methodA的公共API的一部分,因此请对其进行测试。 inner_method是可以更改的实现细节:如果您决定重命名该怎么办? 如果在不修改external_method的外部可见行为的情况下对其进行了少量重构,该outer_method办? AA用户没有(简单)的调用inner_method 单元测试通常仅用于测试您的类用户可以调用的东西(我假设这些是用于单元测试的,因为集成测试这种细粒度的方法会很奇怪-并且相同的原理仍然适用)。

实际上,由于其他一些原因(包括变量捕获),提取另一个函数范围内定义的函数会遇到问题。 您无法知道inner_method仅捕获selfouter_method执行某些逻辑并计算inner_method使用的某些变量。 例如:

class A:
    def outer_method():
        b = 1

        def inner_method():
            return self.a + b

        return inner_method()

另外,您可能在函数定义周围有控制语句,因此如果不运行outer_method ,就无法确定使用哪个定义。 例如:

import random

class A:
    def outer_method():
        if random.random() < 0.5:
            def inner_method():
                return self.a + 1
        else:
            def inner_method():
                return self.a + 2

        return inner_method()

您不能在这里提取inner_method ,因为它们有两个,并且您不知道实际使用的是哪个,直到您运行outer_method

因此,只是不要测试inner_method

如果inner_method确实非常复杂,以至于您想inner_method进行测试(如果这样做,则有原则的测试表明您应该模拟出它的用法,例如,在outer_method中的outer_method ),然后将其outer_method “私有”方法在A

class A:
    def _inner_method(self):
        return self.a + 1
    def outer_method(self):
        return self._inner_method()

原则上的测试表明,您实际上不应该测试下划线方法,但有时有必要这样做。 通过这种方式,您可以像测试其他任何方法一样测试_inner_method 然后,在测试outer_method ,可以通过执行a._inner_method = Mock()来模拟它(其中a是被测试的A对象)。

另外,请使用class A 除非有父类,否则不需要括号。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM