Improve test_bulk_create_objects_validation_error with mixed ok/error case

Use a valid first item (create_data[0]) alongside an invalid second item ({})
so the test exercises both the 'ok' result shape and the atomic rollback of an
item that would otherwise have been persisted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Brian Tiemann 2026-07-08 18:11:34 -04:00
parent d8506f178e
commit 94197efcfb
1 changed files with 21 additions and 10 deletions

View File

@ -2204,31 +2204,42 @@ class DeviceTestCase(APIViewTestCases.APIViewTestCase):
def test_bulk_create_objects_validation_error(self): def test_bulk_create_objects_validation_error(self):
""" """
POST a set of Device objects where all fail validation. DeviceViewSet uses POST a set of Device objects where the first passes and the second fails validation.
SequentialBulkCreatesMixin, so the response should be the structured per-object error DeviceViewSet uses SequentialBulkCreatesMixin, so the response should be the structured
format rather than DRF's default list-of-errors response. per-object format with mixed ok/error statuses, and no objects should be created despite
the first item passing (atomic rollback).
""" """
obj_perm = ObjectPermission(name='Test permission', actions=['add']) obj_perm = ObjectPermission(name='Test permission', actions=['add'])
obj_perm.save() obj_perm.save()
obj_perm.users.add(self.user) obj_perm.users.add(self.user)
obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model)) obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model))
self.add_related_view_permissions(self.create_data[0])
initial_count = self._get_queryset().count() initial_count = self._get_queryset().count()
# Empty objects fail validation (required fields absent) # First item is valid; second is empty (missing required fields) and will fail
response = self.client.post(self._get_list_url(), [{}, {}], format='json', **self.header) response = self.client.post(
self._get_list_url(),
[self.create_data[0], {}],
format='json',
**self.header,
)
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST) self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
self.assertEqual( self.assertEqual(
self._get_queryset().count(), initial_count, self._get_queryset().count(), initial_count,
'No objects should be created when any fail validation', 'No objects should be created when any sibling fails validation',
) )
self.assertIn('detail', response.data) self.assertIn('detail', response.data)
self.assertIn('results', response.data) self.assertIn('results', response.data)
self.assertEqual(len(response.data['results']), 2) self.assertEqual(len(response.data['results']), 2)
for i, result in enumerate(response.data['results']): # First item passed validation
self.assertEqual(result['index'], i) self.assertEqual(response.data['results'][0]['index'], 0)
self.assertEqual(result['status'], 'error') self.assertEqual(response.data['results'][0]['status'], 'ok')
self.assertIn('errors', result) # Second item failed validation
self.assertEqual(response.data['results'][1]['index'], 1)
self.assertEqual(response.data['results'][1]['status'], 'error')
self.assertIn('errors', response.data['results'][1])
class ModuleTestCase(APIViewTestCases.APIViewTestCase): class ModuleTestCase(APIViewTestCases.APIViewTestCase):