我目前在一个项目中,我想测试我的序列化程序的验证。我遇到的问题是,在验证过程中,序列化程序将提供的字段设置为None
,这对我来说似乎并不合理。
更多详情(为简化起见,简称:)
models.py:
class Contract(models.Model):
start_date = models.DateField()
end_date = models.DateField()
serializers.py:
class ContractSerializer(serializers.ModelSerializer):
class Meta:
model = Contract
fields = "__all__"
def validate(self, attrs):
"""
Object-level validation.
Here we validate : start_date is, timewise, prior to end_date
:param attrs:
:return:
"""
if not attrs["start_date"] < attrs["end_date"]:
raise serializers.ValidationError("Sample Error Message.")
return attrs
我使用pytest进行测试和pytest-django。
我的conftest.py:
from pytz import datetime
@pytest.fixture
def valid_contract_json():
start_date = datetime.date(2019, 1, 1)
end_date = datetime.date(2019, 1, 31)
data = {
"start_date": start_date,
"end_date": end_date,
}
return data
我的测试看起来像:
test_serializers.py:
from app.serializers import ContractSerializer
class TestContractSerializer:
def test_validation(self, valid_contract_json):
ContractSerializer(data=valid_contract_json).is_valid(raise_exception=True)
运行此测试时,它失败并显示以下消息:
TypeError:“ datetime.date”和“ NoneType”的实例之间不支持“ <”
我对此进行了调查:
将测试修改为:
def test_validation(self, valid_contract_json):
pprint.pprint(valid_contract_json)
seri = ContractSerializer(data=valid_contract_json).is_valid(raise_exception=True)
# Serialization won't throw exception now
pprint.pprint(seri.data)
这样,我将数据的实际输出传递给序列化器和由序列化器准备的数据。
输出为:
{
'start_date': datetime.date(2019, 1, 1),
'end_date': datetime.date(2019, 1, 31),
}
{
'start_date': '2019-01-01',
'end_date': None,
}
我还检查了调用validate()
时end_date是否已经为None。
答案是肯定的。
所以我的问题是:为什么此处的序列化程序在start_date
下能按预期执行,而在end_date
下却无法执行?
这可能是pytest的隐藏缓存问题吗? 编辑:
我尝试过pytest --cache-clear
并没有解决问题,所以我怀疑这不是一个小问题。
谢谢。
答案 0 :(得分:0)
我发现了发生错误的原因。
问题既不是pytest的问题,也不是所提供的Fixture或数据聚合过程的问题。
问题是我进行了以下字段级验证:
def validate_end_date(self, end_date):
if end_date.day not in (14, monthrange(end_date.year, end_date.month)[1]):
raise serializers.ValidationError()
如您所见,这对我来说执行不佳,因为如果验证通过,我忘记了返回字段值。这样,字段值变为None
。
经验教训:实施字段级验证时,请不要忘记返回初始值。
->之后的方法:
def validate_end_date(self, end_date):
if end_date.day not in (14, monthrange(end_date.year, end_date.month)[1]):
raise serializers.ValidationError()
return start_date