Lav*_*ven 7 python object-initializers
这个问题的关键是帮助单元测试.如果我有一个繁忙的__init__(即__init__复杂的初始化),我不能简单地实例化一个类的对象,但我需要模拟/存根调用在依赖关系中的所有方法__init__.
为了说明这个问题,这里是一个例子:
class SomeClass(object):
def __init__(self, dep1, dep2, some_string):
self._dep1 = dep1
self._dep2 = dep2
self._some_string = some_string
# I would need to mock everything here (imagine some even more
# complicated example)
for dep2element in self._dep2:
dep2element.set_dep(dep1)
self._dep1.set_some_string(some_string)
def fun1(self):
...
def fun2(self):
...
def fun3(self):
...
Run Code Online (Sandbox Code Playgroud)
要测试这些fun*功能,每个测试都必须执行复杂的构造.
class TestSomeClass(TestCase):
def create_SomeClass(self, some_string):
dep1 = Mock()
# mock everything required by SomeClass' constructor
dep2 = Mock()
# mock everything required by SomeClass' constructor
return SomeClass(dep1, dep2, some_string)
def test_fun1(self):
sc = self.create_SomeClass('some string')
...
def test_fun2(self):
sc = self.create_SomeClass('some other string')
...
def test_fun3(self):
sc = self.create_SomeClass('yet another string')
...
Run Code Online (Sandbox Code Playgroud)
我发现这是多余的,并想知道如何在python中优雅地处理这些问题,如果不是通过从构造函数移动工作.
解:
正如@ecatmur建议的那样,要测试一些特定的函数,这段代码应该可以解决问题:
def test_some_method():
mobject = Mock(SomeClass)
SomeClass.fun1(mobject)
Run Code Online (Sandbox Code Playgroud)
通过这种方法,所有方法都将被模拟出来.如果fun1调用你想要执行的其他方法(例如fun2),你可以这样做:
def test_some_method():
mobject = Mock(SomeClass)
mobject.fun2 = SomeClass.fun2.__get__(mobject)
SomeClass.fun1(mobject)
Run Code Online (Sandbox Code Playgroud)
SomeClass.fun2.__get__(mobject)将产生instancemethod哪些将提供正确的绑定.
¡Viva el Python!
原始问题:
最初的问题集中在将完成的工作__init__转移到单独的init方法和不同的问题旋转该方法.我通常的做法是做到这一点
class SomeClass(object):
def __init__(self, dep1, dep2, some_string)
self._dep1 = dep1
self._dep2 = dep2
# lots of mumbo-jumbo here...
Run Code Online (Sandbox Code Playgroud)
成为这个
class SomeClass(object):
def __init__(self, dep1, dep2)
self._dep1 = dep1
self._dep2 = dep2
def initiate(self, some-string)
# lots of mumto-jumbo here...
Run Code Online (Sandbox Code Playgroud)
一般的情绪是,移动工作__init__不是一种常见的做法,对经验丰富的python开发人员来说毫无意义.
如果您编写初始化函数,__init__那么经验丰富的开发人员肯定会将您的代码视为孩子的游乐场.
如果您担心能够在不运行__init__方法的情况下创建看起来像您的类实例的对象,那么使用Mock:
def test_some_method():
mock_object = Mock(MyClass)
MyClass.some_method(mock_object)
Run Code Online (Sandbox Code Playgroud)
__init__实际上无法返回任何东西;如果您考虑如何使用它,这应该很明显:
class Example(object):
def __init__(self, x):
self.x = x
return ANYTHING
e = Example(1) # how are you going to get ANYTHING back?
Run Code Online (Sandbox Code Playgroud)
使用与initialize()分开的方法__init__似乎很愚蠢-整个要点是,初始化器应在创建对象时自动运行,因此示例初始化应类似于
scobj = SomeClass(dep1, dep2, 'abcdef')
# scobj.initialize('abcdef') # <= separate call not needed!
Run Code Online (Sandbox Code Playgroud)
编辑:
如果您确实需要在中加入代码__init__,建议将其放在私有方法中,然后从中调用__init__,例如:
class Example2(object):
def __init__(self, a, b, c):
self._init_connection(a)
self._init_display(b)
self.c = c
def _init_connection(self, a):
self.conn = make_connection(a)
def _init_display(self, b):
self.disp = make_display(b)
Run Code Online (Sandbox Code Playgroud)
...这很好,因为
| 归档时间: |
|
| 查看次数: |
2487 次 |
| 最近记录: |