我的单元测试中有一个带有多个外键的模型的工厂函数。我希望该工厂函数是可变参数,允许用户指定要用作外键的对象作为关键字参数,但调用相关的工厂函数为任何遗漏的函数生成一个新函数。
我原来写的是:
def model_factory(i, **kwargs):
"""Create a new Model for testing"""
test_model_data = {
'fk1': kwargs.get('fk1', fk1_factory(i)),
'fk2': kwargs.get('fk2', fk2_factory(i)),
'fk3': kwargs.get('fk3', fk3_factory(i)),
}
return Model.objects.create(**test_model_data)
但即使关键字存在,也会调用fkN_factory()方法,从而导致许多干扰我的测试的副作用。我的问题是,是否有一种更简单的方法来做我想做的事情而不会导致大量不必要的函数调用,而不是我现在所拥有的,更像是:
def model_factory(i, **kwargs):
"""Create a new Model for testing"""
test_model_data = {
'fk1': kwargs.get('fk1', None),
'fk2': kwargs.get('fk2', None),
}
if kwargs['f1'] is None:
kwargs['f1'] = fk1_factory(i)
if kwargs['f2'] is None:
kwargs['f2'] = fk2_factory(i)
答案 0 :(得分:2)
您希望以某种方式分解重复的代码。最简单的是:
def get_value(mapping, key, default_func, *args):
try:
return mapping[key]
except KeyError:
return default_func(*args)
# ...
test_model_data = {
'fk1': get_value(kwargs, 'fk1', fk1_factory, i),
'fk2': get_value(kwargs, 'fk2', fk2_factory, i),
# etc.
}
几乎与原始的非工作版本一样简单。
你可以更进一步:
def map_data(mapping, key_factory_map, *args):
return {key: get_value(mapping, key, factory, *args)
for key, factory in key_factory_map.items()}
# …
test_model_data = map_data(kwargs, {
'fk1': fk1_factory,
'fk2': fk2_factory,
# …
}, i)
但我不确定这实际上更好。 (如果你有一个显而易见的地方来定义那个线外的工厂映射,它可能是;如果不是,可能不是。)