Pytest. AssertionError при отправке POST-запроса в тестах DjangoRestFramework
Есть модель заказа:
class Order(models.Model):
""" Модель заказов """
user = models.ForeignKey(
User,
verbose_name="Пользователь",
on_delete=models.CASCADE,
related_name="order"
)
status = models.TextField(
OrderStatusChoices.choices,
default=OrderStatusChoices.NEW
)
products = models.ManyToManyField(Product, related_name='order', through='Position')
count = models.PositiveIntegerField(editable=False)
total = models.FloatField(editable=False)
created_at = models.DateTimeField("Создано", auto_now_add=True)
updated_at = models.DateTimeField("Обновлено", auto_now=True)
def __str__(self):
return "User: {} has {} items in order. Their total is ${}".format(self.user, self.count, self.total)
class Meta:
verbose_name = "Заказ"
verbose_name_plural = "Заказы"
ordering = ["created_at"]
промежуточная таблица Position для связи Order и Product:
class Position(models.Model):
""" Позиции товаров """
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='position')
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='position')
quantity = models.PositiveIntegerField()
def __str__(self):
return "This entry contains {} {}(s).".format(self.quantity, self.product.name)
class Meta:
verbose_name = "Наименование"
verbose_name_plural = "Наименования"
Сериализаторы:
class OrderSerializer(serializers.ModelSerializer):
""" Сериализатор списка заказов """
user = serializers.SlugRelatedField(
slug_field='username',
read_only=True,
)
products = PositionSerializer(many=True, source='position.all')
class Meta:
model = Order
fields = '__all__'
read_only_fields = ('status',)
def create(self, validated_data):
validated_data['user'] = self.context["request"].user
positions = validated_data.pop(
'position')
positions_objs = []
validated_data['count'] = 0
validated_data['total'] = 0
order = super().create(validated_data)
for position in positions.values():
for item in position:
price = Product.objects.get(id=item['product'].id).price
validated_data['total'] += price * item['quantity']
validated_data['count'] += item['quantity']
positions_objs.append(Position(quantity=item['quantity'], product=item['product'], order=order))
order.count = validated_data['count']
order.total = validated_data['total']
order.save()
Position.objects.bulk_create(positions_objs)
return order
class OrderDetailSerializer(serializers.ModelSerializer):
""" Сериализатор конкретного заказа """
user = serializers.SlugRelatedField(
slug_field='username',
read_only=True,
)
position = PositionSerializer(many=True, read_only=True)
class Meta:
model = Order
fields = ('user', 'status', 'total', 'count', 'position', 'created_at', 'updated_at')
def update(self, instance, validated_data):
"""Метод для обновления + проверка на допустимость изменения"""
if self.context['request'].user.is_authenticated:
if validated_data['status'] == 'CANCELLED':
instance.status = validated_data.get('status', instance.status)
instance.updated_at = datetime.now()
instance.save()
return instance
else:
raise ValidationError({"Order": "Авторизованный пользователь может менять статус только на 'Отменён'"})
elif self.context['request'].user.is_staff or self.context['request'].user.is_superuser:
instance.status = validated_data.get('status', instance.status)
instance.updated_at = datetime.now()
instance.save()
return instance
else:
raise ValidationError({"Order": "Менять статус заказа может только админ"})
Всё прекрасно работает. Через Api DRF всё работает - запросы на создание заказа отправляются и сохраняются в БД. Также использую Talend Api Tester. В нём тоже всё прекрасно. Но в тестах происходит ошибка. Тест создания:
@pytest.mark.django_db
def test_create_order_and_positions_by_authenticated_client(product_factory, authenticated_client):
""" Тест на создание заказа и позиций заказа """
product_factory(_quantity=3)
url = reverse("orders-list")
order = {'products': [{
"product": 1,
"quantity": 1
},
{
"product": 2,
"quantity": 2
},
{
"product": 3,
"quantity": 5
}]}
resp = authenticated_client.post(url, order, format='json')
print(resp.json())
assert resp.status_code == HTTP_201_CREATED
Print выдаёт следующую информацию:
FAILED [100%]{'products': ['Обязательное поле.']}
Файл settings проекта:
REST_FRAMEWORK = {
'TEST_REQUEST_DEFAULT_FORMAT': 'json'
}
Если убрать из настроек формат по умолчанию, либо не передавать с запросом, то ничего не меняется - та же ошибка. Не могу понять, что не так. Если надо что-то добавить - пишите
Ответы (1 шт):
Нашёл ответ:
@pytest.mark.django_db
def test_create_order_and_positions_by_authenticated_client(product_factory, authenticated_client):
""" Тест на создание заказа и позиций заказа """
product_factory(_quantity=3)
url = reverse("orders-list")
order = {'products': [{
"product": 1,
"quantity": 1
},
{
"product": 2,
"quantity": 2
},
{
"product": 3,
"quantity": 5
}]}
resp = authenticated_client.post(url, order, content_type='application/json')
print(resp.json())
assert resp.status_code == HTTP_201_CREATED
нужно было вместо format='json' указать content_type='application/json'. Я сперва написал тест с указанием формата в настройках, как это сказано в документации - не сработало и я полез в интернет. Мне ответили, что нужно, либо в настройках указать по умолчанию формат(как у меня сделано было), либо дописать format='json'. Я сделал и это не помогло, поэтому написал здесь, но пока ждал ответа нашёл ответ сам.