Я бы сказал, что нет смысла тестировать clean_fields
, поскольку уже является частью очень хорошо протестированной кодовой базы Django. Но если вы настаиваете на его тестировании, вам определенно не стоит издеваться над User
.
Давайте посмотрим на код, который вы пытаетесь проверить здесь (это отрывок из clean_fields ):
raw_value = getattr(self, f.attname)
if f.blank and raw_value in f.empty_values:
continue
try:
setattr(self, f.attname, f.clean(raw_value, self))
except ValidationError as e:
errors[f.name] = e.error_list
Мы видим, что он проходит через каждое поле вмодель, пытающаяся вызвать свой метод clean
( source ):
def clean(self, value):
"""
Validate the given value and return its "cleaned" value as an
appropriate Python object. Raise ValidationError for any errors.
"""
value = self.to_python(value)
self.validate(value)
self.run_validators(value)
return value
OneToOneField
сама не вводит ни один из этих методов, это делается выше в иерархии классов, вForeignKey
класс. И вот основная часть метода validate
:
using = router.db_for_read(self.remote_field.model, instance=model_instance)
qs = self.remote_field.model._default_manager.using(using).filter(
**{self.remote_field.field_name: value}
)
qs = qs.complex_filter(self.get_limit_choices_to())
if not qs.exists():
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={
'model': self.remote_field.model._meta.verbose_name, 'pk': value,
'field': self.remote_field.field_name, 'value': value,
}, # 'pk' is included for backwards compatibility
)
Как видите, вся проверка состоит только из конструкции запроса с вызовом базы данных! Поэтому, если вы пытаетесь избежать попадания в базу данных, вам следует просто полностью пропустить проверку любых внешних ключей:
def test_create_profile_fail(self):
with self.assertRaises(ValidationError):
test_profile = Profile(**self.profile_data)
test_profile.clean_fields(exclude=['user']) # don't forget to explain your decision in the comments
Итак, в заключение, лучший способ издеваться над Пользователем - это фактически создать его вбаза данных. Если вы хотите избежать шаблонов, вы можете использовать пакет factory_boy .