side_effect第三次学习
(1)side_effect理解
需求:mock网络图特征获取api,由于其结构是直接设置features,features里面已经包含了其他例如变更等特征,因此,该mock跟输入有关需要用side_effect实现,具体如下:@mock.patch.object(NetworkShixinFeatures, ‘set_shixin_features_dto’),
需要 self.t_h.set_api_return_value(locals(), get_judgedoc_shinfo_time_node_api, company_name, self.__get_face_judgedoc_api_default());再定义
def side_effect(*arg):
# 统计调用次数
features_dto = arg[0]
if not isinstance(features_dto, ShixinFeaturesDto):
raise BizException(u'输入对象类型不匹配')
features_dto.network_share_cancel_cnt = 1
features_dto.cancel_cnt = 2
features_dto.network_share_zhixing_cnt = 3
features_dto.network_share_judge_doc_cnt = 4
features_dto.net_judgedoc_defendant_cnt = 5
features_dto.judge_doc_cnt = 6
features_dto.network_share_or_pos_shixin_cnt = 7
return features_dto
然后set_shixin_features_dto.side_effect = side_effect,即将mock的api——set_shixin_features_dto通过side_effect的方式mock,arg,*arg表示实际set_shixin_features_dto函数的参数顺序,与位置有关,**arg与名字相关-键值的形式传参。*arg中第一个参数为features,因此,将其取出来: features_dto = arg[0],然后再进行设置。
之前的side_effect是返回一个函数:
def __side_effect_judgedoc_shinfo(self, verify_open_from):
time_map_judgedoc_shinfo = self.__get_time_map_judgedoc_shinfo()
def inner_effect(*arg):
start_time = arg[1]
self.assertEqual(verify_open_from, start_time)
to_time = arg[2]
return time_map_judgedoc_shinfo[to_time]
return inner_effect
返回函数的理解:直接将输入设置一下不能满足该函数应返回的功能,需要借助于一个函数inner_effect,来调用其他的函数 time_map_judgedoc_shinfo = self.__get_time_map_judgedoc_shinfo(),实现返回。
真正的函数是这样的,其返回的形式应该为这样的形式:time_map_judgedoc_shinfo[to_time]
:
def get_judgedoc_shinfo_time_node_api(self, company_name, from_time, to_time):
"""
查询裁判文书ID
see wiki: http://192.168.31.157:8200/doku.php?id=platform:apis:court:judgedocshotinfo#查询裁判文书id
PATH: /api/judgedoc/shinfo
http://192.168.31.121:9488/api/judgedoc/shinfo?companyName=重庆欧枫投资有限公司&from=2016-01-05&to=2018-05-03
:return:
"""
url_network_company_format = GET_JUDGEDOC_SHINFO + u'{}&from={}&to={}'
url = url_network_company_format.format(company_name, from_time, to_time)
data = APiH.get_url_dict(url)
return self.__data_verify(data)
@mock.patch.object(FeatureExtractTimeNodeApiSvc, 'get_judgedoc_shinfo_time_node_api')
@mock.patch.object(FeatureExtractApiSvc, 'get_cmp_basic_api')
@mock.patch.object(FeatureExtractApiSvc, 'get_cmp_shixin_api')
@mock.patch.object(NetworkShixinFeatures, 'set_shixin_features_dto')
def test_mock_get_feature(self, set_shixin_features_dto, get_cmp_shixin_api, get_cmp_basic_api, get_judgedoc_shinfo_time_node_api):
# -- given
feature_deal = FeaturesDealShiXinSvc()
# mock main company
# main_company_info_path = 'main_company_api_info_stub.json'
# main_company_info = self.t_h.load_main(main_company_info_path)
# fake main judge_doc_info
# fake main cmp_info
company_name = u'重庆嘉禾一品餐饮管理有限公司'
self.t_h.set_api_return_value(locals(), get_cmp_shixin_api, company_name, self.__get_no_shixin_info_api())
self.t_h.set_api_return_value(locals(), get_cmp_basic_api, company_name, self.__get_cmp_info_api())
self.t_h.set_api_return_value(locals(), get_judgedoc_shinfo_time_node_api, company_name, self.__get_face_judgedoc_api_default())
def side_effect(*arg):
# 统计调用次数
features_dto = arg[0]
if not isinstance(features_dto, ShixinFeaturesDto):
raise BizException(u'输入对象类型不匹配')
features_dto.network_share_cancel_cnt = 1
features_dto.cancel_cnt = 2
features_dto.network_share_zhixing_cnt = 3
features_dto.network_share_judge_doc_cnt = 4
features_dto.net_judgedoc_defendant_cnt = 5
features_dto.judge_doc_cnt = 6
features_dto.network_share_or_pos_shixin_cnt = 7
return features_dto
set_shixin_features_dto.side_effect = side_effect
self.__assert_result_code_normal(feature_deal)
self.__assert_result_code_saic_none(feature_deal, get_cmp_basic_api)
(2)side_effect的活用
side_effect:
需求:当前mock两种情况:1)未失信正常;2)未失信无工商数据;3)失信;
已经在主测试中定义好了未失信的mock,当我想要mock失信的时,需要重新传入关于失信api函数的mock,在失信的测试中重新定义关于失信后的api返回值,像这样实现:
def __assert_return_shi_xin(self, biz_svc, company_name, get_shixin_features):
"""
失信企业
"""
# given
get_shixin_features.return_value = self._get_feature_deal_do(
BizConsts.ENTERPRISE_CODE_NORMAL, BizConsts.DATA_STATE_SAIC_NONE, True)
# when
risk_res = biz_svc.get_model_risk_result(company_name, False)
# then
self.t_u.assert_equal(BizConsts.OUTPUT_STATUS_SHIXIN, risk_res.status_code)
self.t_u.assert_none(risk_res.evaluate_dto)
其中定义的函数shixin设置为True:
@staticmethod
def _get_feature_deal_do(enterprise_code, result_code, is_shi_xin=False):
features = ShixinFeaturesDto()
return ShinXinFeaturesDealDo(
features=features,
enterprise_status=u'已经吊销的公司',
enterprise_code=enterprise_code,
result_code=result_code,
industry_code='xxx',
is_shi_xin=is_shi_xin
)
测试的主类:
class TestBizShixinController(TestCase):
t_u = TestUtils()
@mock.patch.object(ModelDescribeSvc, 'get_describe')
@mock.patch.object(EvaluateShixinSvc, 'evaluate_by_features')
@mock.patch.object(EvaluateShixinSvc, 'evaluate_by_prob')
@mock.patch.object(ShixinCompaniesFeaturesSvc, 'get_features_by_company_name_maybe')
@mock.patch.object(ShixinCompaniesFeaturesSvc, 'add_or_update_features')
@mock.patch.object(ShixinCompaniesFeaturesSvc, 'delete_by_company_name')
@mock.patch.object(RemarkCompanyListDbSvc, 'find_prob_maybe_by_company_name')
@mock.patch.object(FeaturesDealShiXinSvc, 'get_shixin_features')
def test_get_model_risk_result(
self, get_shixin_features, find_prob_maybe_by_company_name, delete_by_company_name,
add_or_update_features, get_features_by_company_name_maybe, evaluate_by_prob,
evaluate_by_features, get_describe
):
"""
采用-数据库黑白名单部分产生-预测
"""
# -- given
biz_svc = BizShixinController()
company_name = u'重庆嘉禾一品餐饮管理有限公司'
cancel_rate = 0.5
# mocks
get_shixin_features.return_value = self._get_feature_deal_do(BizConsts.ENTERPRISE_CODE_NORMAL,
BizConsts.DATA_STATE_NORMAL)
find_prob_maybe_by_company_name.return_value = Maybe.some(DataConsts.CANCEL_PROB_KNOWN_BLACK)
add_or_update_features.return_value = None
get_features_by_company_name_maybe.return_value = Maybe.none()
get_describe.return_value = u'风险文字描述'
delete_by_company_name.return_value = None
evaluate_by_features.return_value = EvaluateDto(risk_prob=cancel_rate, risk_rank=BizConsts.RISK_RANK_HIGH)
self.__assert_fake_predict(biz_svc, company_name, cancel_rate, evaluate_by_prob)
self.__assert_true_predict(biz_svc, cancel_rate, company_name, find_prob_maybe_by_company_name,
get_shixin_features)
self.__assert_return_cancel(biz_svc, company_name, find_prob_maybe_by_company_name, get_shixin_features)
self.__assert_return_no_satic(biz_svc, company_name, get_shixin_features)
self.__assert_return_shi_xin(biz_svc, company_name, get_shixin_features)