Python-mock:如何测试是否调用了super()
我有以下结构:
class A(Object):
def method(self):
return 'a'
class B(A):
def __init__(self, test):
self.test = test
def method(self):
if self.test:
return super(A, self).method(self)
else:
return 'b'
我想做的是写一个测试用例,来检查如果 self.test 为真,那么父类的函数和 A 类的方法都被调用了。
我该怎么做呢?我应该模拟什么?
进阶问题:如果 A 类和 B 类在不同的模块里,而且它们的名字是一样的。这样的话,我就会写成:class A(module1.A):这样会影响模拟的方式吗?
2 个回答
0
为了进一步说明@Malina的精彩回答,如果你无法对模块A的方法进行修改(比如A是在一个第三方库中,属于一个复杂的旧系统,或者是在运行时动态创建的等等),你仍然可以通过在类B中创建另一个专门用于测试的方法来测试这个功能。
修改后的类 B
import A
class B(A):
def __init__(self, test):
self.test = test
def method(self):
if self.test:
self._delegate_to_A() # Move the super call to a separate method
else:
return 'b'
def _delegate_to_A(self)
return super(A, self).method(self)
修改后的类 B
的测试代码
import mock, unittest
class TestB(unittest.TestCase):
# Patch B's `delegate` method instead of A
@mock.patch("B._delegate_to_A")
def test_super_method(self, mock_super):
B(True).method()
self.assertTrue(mock_super.called)
@mock.patch("B._delegate_to_A")
def test_super_method(self, mock_super):
B(False).method()
self.assertFalse(mock_super.called)
12
正如@MartijnPieters所说,测试是否调用了super通常是检查实现细节,而不是测试一个合约。不过,有时候检查具体的实现也是有必要的,或者父类可能有要求必须调用super的合约。为了测试是否调用了super,可以使用一个模拟对象,正如@mgilson提到的。下面是详细的说明:
import mock, unittest
class TestB(unittest.TestCase):
@mock.patch("A.method")
def test_super_method(self, mock_super):
B(True).method()
self.assertTrue(mock_super.called)
@mock.patch("A.method")
def test_super_method(self, mock_super):
B(False).method()
self.assertFalse(mock_super.called)
你需要在补丁中指定完整的命名空间。例如,@mock.patch("module.submodule.A.method")
。这可以用于A类中的任何方法,包括__init__
;语法是完全一样的。