django - Django:模拟模型的创建方法
问题描述
我有一个名为 Job 的模型。我创建了一个文件 services.py,我将在其中放置一些方法和业务逻辑。我正在尝试使用 Mock 测试它们。问题是如果我想模拟 Job.objects.create 它,它会给我一个错误。
服务.py
from .models import Job
class CreateJob:
def __init__(
self,
title,
email,
):
self._title = title
self._email = email
def execute(self):
# Create dictionary with the keys without the first _ in the name
params = {k[1:] if k[0] == '_' else k:v for k,v in self.__dict__.items() if v is not None}
job = Job.objects.create(**params)
return job
这是 mi 测试用例,运行正常
class TestExecute(TestCase):
def setUp(self):
self._use_case = CreateJob(
title='How to test a job creation',
email='john.smith@example.com',
)
def test_return_job_type(self):
result = self._use_case.execute()
assert isinstance(result, Job)
但是如果我想修补 create 方法,所以我不打数据库,像这样
def create_job(params):
return Job(**params)
@patch.object(Job.objects, 'create', side_effect=create_job)
class TestExecute(TestCase):
def setUp(self):
self._use_case = CreateJob(
title='How to test a job creation',
email='john.smith@example.com',
)
def test_return_job_type(self,mock_create):
result = self._use_case.execute()
assert isinstance(result, Job)
我有以下错误:TypeError: create_job() got an unexpected keyword argument 'title'
这是跟踪:
services.py:100: in execute
job = Job.objects.create(**params)
/usr/lib/python3.6/unittest/mock.py:939: in __call__
return _mock_self._mock_call(*args, **kwargs)
def _mock_call(_mock_self, *args, **kwargs):
self = _mock_self
self.called = True
self.call_count += 1
_new_name = self._mock_new_name
_new_parent = self._mock_new_parent
_call = _Call((args, kwargs), two=True)
self.call_args = _call
self.call_args_list.append(_call)
self.mock_calls.append(_Call(('', args, kwargs)))
seen = set()
skip_next_dot = _new_name == '()'
do_method_calls = self._mock_parent is not None
name = self._mock_name
while _new_parent is not None:
this_mock_call = _Call((_new_name, args, kwargs))
if _new_parent._mock_new_name:
dot = '.'
if skip_next_dot:
dot = ''
skip_next_dot = False
if _new_parent._mock_new_name == '()':
skip_next_dot = True
_new_name = _new_parent._mock_new_name + dot + _new_name
if do_method_calls:
if _new_name == name:
this_method_call = this_mock_call
else:
this_method_call = _Call((name, args, kwargs))
_new_parent.method_calls.append(this_method_call)
do_method_calls = _new_parent._mock_parent is not None
if do_method_calls:
name = _new_parent._mock_name + '.' + name
_new_parent.mock_calls.append(this_mock_call)
_new_parent = _new_parent._mock_new_parent
# use ids here so as not to call __hash__ on the mocks
_new_parent_id = id(_new_parent)
if _new_parent_id in seen:
break
seen.add(_new_parent_id)
ret_val = DEFAULT
effect = self.side_effect
if effect is not None:
if _is_exception(effect):
raise effect
if not _callable(effect):
result = next(effect)
if _is_exception(result):
raise result
if result is DEFAULT:
result = self.return_value
return result
ret_val = effect(*args, **kwargs)
E TypeError: create_job() got an unexpected keyword argument 'title'
解决方案
您必须为create_job
方法定义您接受的参数。目前它只接受 1 个名为params
. 你应该这样写:
def create_job(**params):
return Job(**params)
并且 python 的约定是使用*args
and **kwargs
,尽管不需要使用它们。
推荐阅读
- javascript - 将数据发送到后端 submit() 不是函数
- oracle - Oracle 7 DB 文件是否与更高版本兼容?甲骨文 9 还是 10G?
- ios - 在 UserDefaults 中编辑结构而不会丢失数据 Swift
- ansible - 无法通过 ssh 连接到主机:共享连接到
关闭 - c# - Linq 查询在 SQL 中生成不同的结果
- android - Android RecyclerView 中的 Glide 缓存不起作用
- java - Spring Data Rest 存储库偶尔不会导出
- python - BeautifulSoup 抓取位于 csv 中的 URL,然后输出到新的 csv
- c - 为什么 scanf 不读取零
- json - 在flutter的下拉框中填充json api数据