模拟 Class 函数
Mocking Class Functions
我正在尝试对一个 class 进行单元测试,它有一个相当复杂的 __init__,一个涉及对服务器和外部组件的调用。我发现你可以使用 unittest MagicMock 来伪造一个 init。
class my_class:
def __init__(self, arg1, arg2):
self.var = arg1
self.method1(arg2)
def method1(self, arg):
var = "Hello " + arg
self.method2(var)
def method2(self, var):
print(var)
SELF = MagicMock()
my_calss.my_class.__init__(SELF, arg1, arg2)
太棒了,因为所有与服务器通信的代码都在其他方法中,我可以确保 __init__ 调用某些方法。
当我想测试一个调用另一个方法的方法时,问题就来了。
SELF = MagicMock()
my_class.__init__(SELF, arg1, arg2)
SELF.method2 = my_class.method2
my_class.method1(SELF, arg)
我希望 method2 中的 self 是 SELF,但 method2 永远不会得到 self。
有没有办法确保 method2 获得模拟的 SELF?
或者另一种测试方法 class 不涉及大量补丁的方法?
我认为 MagicMock
无法实现。
一种方法是使用 __new__
class 方法创建 class 的实例而不调用它的 __init__
方法,然后在根据需要测试设置。
例如
instance = my_class.__new__(my_class)
# Manually initialize properties as needed.
instance.usually_set_by_init = 3
# Use the instance like normal.
instance.method1(arg)
如果您还没有听说过 __new__
,这可能看起来很奇怪,但了解 a = A()
等同于 a = A.__new__(A); a.__init__()
是很有帮助的。
您可以直接删除 class 而不是模拟。
class MyClassStub(MyClass):
def __init__(self):
pass # bypass parents init
我正在尝试对一个 class 进行单元测试,它有一个相当复杂的 __init__,一个涉及对服务器和外部组件的调用。我发现你可以使用 unittest MagicMock 来伪造一个 init。
class my_class:
def __init__(self, arg1, arg2):
self.var = arg1
self.method1(arg2)
def method1(self, arg):
var = "Hello " + arg
self.method2(var)
def method2(self, var):
print(var)
SELF = MagicMock()
my_calss.my_class.__init__(SELF, arg1, arg2)
太棒了,因为所有与服务器通信的代码都在其他方法中,我可以确保 __init__ 调用某些方法。
当我想测试一个调用另一个方法的方法时,问题就来了。
SELF = MagicMock()
my_class.__init__(SELF, arg1, arg2)
SELF.method2 = my_class.method2
my_class.method1(SELF, arg)
我希望 method2 中的 self 是 SELF,但 method2 永远不会得到 self。 有没有办法确保 method2 获得模拟的 SELF?
或者另一种测试方法 class 不涉及大量补丁的方法?
我认为 MagicMock
无法实现。
一种方法是使用 __new__
class 方法创建 class 的实例而不调用它的 __init__
方法,然后在根据需要测试设置。
例如
instance = my_class.__new__(my_class)
# Manually initialize properties as needed.
instance.usually_set_by_init = 3
# Use the instance like normal.
instance.method1(arg)
如果您还没有听说过 __new__
,这可能看起来很奇怪,但了解 a = A()
等同于 a = A.__new__(A); a.__init__()
是很有帮助的。
您可以直接删除 class 而不是模拟。
class MyClassStub(MyClass):
def __init__(self):
pass # bypass parents init