我正在编写一个单元测试代码来测试在A类中定义的函数“ a”,该函数调用在“ B”类中定义的函数“ b”。如何使“ a”调用b-mocking函数?
#-------------------------------------------------
class B :
def __init__(self):
print('hello B')
def b(self):
return False
#------------------------------------------------
class A :
def __init__(self):
print('hello A')
def a(self,a,b):
ret = B().b()
if ret == True:
return 0
else :
return a+b
#-----------------------------------------------
class TestA(unittest.TestCase):
def setUp(self):
pass
def return_true(self):
return True
@patch('__main__.B')
def test_a_in_A(self,mocked_B):
mocked_B.b.return_value = True
assert A().a(2,3) == 0
#---------------------------------------------
if __name__ == '__main__':
unittest.main()
我期望断言A()。a(2,3)== 0 的输出为test OK
但实际输出为AssertionError
注意:当我运行声明A()。a(2,3)== 5 时,测试返回test OK
,这意味着该模拟无法正常工作。
答案 0 :(得分:1)
好的,很长的版本:模拟是指用简化形式替换某些东西。但是,您不能嘲笑未使用的东西。没有任何意义。
让我们在这里查看您的代码:
<?= Html::beginForm(['selected'], 'post'); ?>
<?= GridView::widget([
'dataProvider'=>$dataProvider,
'filterModel'=>$searchModel,
'toolbar'=>['{export}', '{toggleData}',],
'panel'=> ['type'=>'primary',
'after'=>$object_data->enableMakePayment =='on' ? Html::submitButton('Make Payment', array('submit'=>'actionSelected'),['class'=>'btn btn-success']):'',
],
'columns'=> xxx,
'showPageSummary'=>true,
]);?>
<?= Html::endForm();?>
您正在此函数内构造一个新的B(),因此它没有在嘲笑B上的测试中其他地方设置的return_value。拥有模拟对象的全部要点是您传递了模拟,并获得了可预测的行为。您不能模拟完全封装在要测试的函数中的对象。
在这里,我修改了您的代码以使用一个(可能是模拟的)B对象。我将整数参数从a,b重命名为x,y,因为它太混乱了。他们与A或B无关。
您还忘记了一些进口。
def a(self,a,b):
ret = B().b()
if ret == True:
return 0
else :
return a+b
根据要求,以下是修订版本,对现有代码的影响较小:
import unittest
from unittest.mock import patch
class B :
def __init__(self):
print('hello B')
def b(self):
return False
class A :
def __init__(self):
print('hello A')
def a(self, x, y, b):
if b.b():
return 0
else:
return x + y
class TestA(unittest.TestCase):
def setUp(self):
pass
def return_true(self):
return True
@patch('__main__.B')
def test_a_in_A(self,mocked_B):
mocked_B.b.return_value = True
assert A().a(2,3, mocked_B) == 0
if __name__ == '__main__':
unittest.main()
我将测试更改为“ self.bb()为True”,以避免遇到未初始化return_value但仍评估为true的MagicMock对象,因为...这是一个实例,而bool(object)就是这样工作的。
在这里,您仍然必须传递将return_value设置为所需值的模拟实例,因此测试将是
class A :
def __init__(self, b=None):
# this instance can use a member instance of B
self.b = b if b else B()
print('hello A')
def a(self, x, y):
if self.b.b() is True:
return 0
else:
return x + y
如果要模拟对象替换某些东西,则必须要替换一些东西。查找“依赖注入”可能是有帮助的,“依赖注入”是相同基本思想的另一个名称。