如何使用Factory对象覆盖django模型,以避免命中数据库。
models.py
from django.db import models
class ApplicationType(models.Model):
"""
Types of applications available in the system/
"""
title = models.CharField(max_length=30)
def __str__(self):
return self.title
utils.py
from .models import ApplicationType
self.base_details = {}
def get_application_type(self, value):
"""
Get types of applications. When successful it Populates the
self.base_details with an application_type key
Args:
value (object): value to be parsed
Returns:
bool: True when value is ok, Else false
Raises:
"""
item_name = "Application Type"
self.base_details['application_type'] = None
try:
if value:
try:
result = ApplicationType.objects.get(title=value) # <== How do I avoid hitting this DB object?
self.base_details['application_type'] = result.id
return True
except ApplicationType.DoesNotExist:
self.error_msg = "Invalid Value: {}".format(item_name)
return False
else:
self.error_msg = "Blank Value: {}".format(item_name)
return False
except:
raise
因此,为了测试,我创建了一个ApplicationType工厂
tests.py
import factory
import pytest
application_types = ['Type 1', 'Type 2']
class ApplicationTypeFactory(factory.Factory):
class Meta:
model = ApplicationType
title = "application_type_title"
@pytest.mark.django_db()
def test_get_application_type_populates_dict_when_value_provided_exists_in_database(self):
"""Populates base_details dict when value is found in database"""
for entry in application_types:
application_type = ApplicationTypeFactory.build(title=entry)
assert self.base_info_values.get_application_type(entry) == True
assert self.base_info_values.base_details["application_type"] is not None
因此,您将如何编写一个测试,避免在代码中间的ApplicationType.objects.get()
查询中访问数据库?我可以将“模型”作为参数传递给函数吗?这是一个好的设计吗?
您可以自由地为应用程序/功能提供替代结构,尤其是为了在这种情况下进行更好的测试。
正在运行Python3.5,pytest-django和factory_boy
答案 0 :(得分:1)
您可以修补对数据库的调用,以返回您设置的预定义值。在你的情况下,你可以做这样的事情:
import factory
import pytest
from unittest.mock import Mock, patch
application_types = ['Type 1', 'Type 2']
@pytest.mark.django_db()
@patch('ApplicationType.objects.get')
def test_get_application_type_populates_dict_when_value_provided_exists_in_database(self, db_mocked_call):
"""Populates base_details dict when value is found in database"""
mocked_db_object = {'id': 'test_id'}
db_mocked_call.return_value = mocked_db_object
for entry in application_types:
application_type = ApplicationTypeFactory.build(title=entry)
assert self.base_info_values.get_application_type(entry) == True
assert self.base_info_values.base_details["application_type"] is not None
我建议您检查pytest.parametrize以避免在测试中使用for循环,请在此处详细了解:http://doc.pytest.org/en/latest/parametrize.html
在您的示例中,测试可能如下所示:
@pytest.mark.django_db()
@pytest.mark.parametrize("entry", ['Type 1', 'Type 2'])
@patch('ApplicationType.objects.get')
def test_get_application_type_populates_dict_when_value_provided_exists_in_database(self, db_mocked_call, entry):
"""Populates base_details dict when value is found in database"""
mocked_db_object = {'id': 'test_id'}
db_mocked_call.return_value = mocked_db_object
application_type = ApplicationTypeFactory.build(title=entry)
assert self.base_info_values.get_application_type(entry) == True
assert self.base_info_values.base_details["application_type"] is not None