Reputation: 1717
I have the following view, which excepts POST requests, and serializes an objects data (a Draftschedule) to create a new copy (a FrozenSchedule):
from reports.tasks import create_frozen_schedule
def freeze_schedule(request, pk):
"""Valid post request will freeze a Draft Schedule serializing its data"""
client = get_object_or_404(Client, draftschedule=pk)
try:
# Serialize data into a FrozenSchedule object
frozenschedule = create_frozen_schedule(pk, request.user.id)
except IntegrityError:
# Warn user if action failed
messages.warning(request, "A Schedule of this Type already exists")
return redirect(client.draftschedule)
else:
# If Schedule is Frozen successfully
messages.success(request, "Schedule Frozen")
return redirect(frozenschedule)
I'm trying to write a test to assert certain things happen after an IntegrityError is raised. I'm struggling to understand why it's failing, it's not immediately obvious to me where I'm going wrong since I'm fairly inexperienced with mocking / patching.
I've tried to mock the create_frozen_schedule
function to raise an IntegrityError when called:
def setUp(self):
self.url = reverse(
'reports:draftschedule-freeze',
args=[self._client.draftschedule.pk]
)
super(TestFreezeSchedule, self).setUp()
@patch('reports.tasks.create_frozen_schedule')
def test_freeze_schedule_with_conflict(self, mock_freeze):
mock_freeze.side_effect = IntegrityError
with self.assertRaises(IntegrityError):
self.client.post(self.url)
# More unit tests following same premise...
But I end up with the following error:
.......................................................................................F............
======================================================================
FAIL: test_freeze_schedule_with_conflict (reports.tests.test_views.TestFreezeSchedule)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python3.4/unittest/mock.py", line 1136, in patched
return func(*args, **keywargs)
File "/home/jwe/piesup2/reports/tests/test_views.py", line 495, in test_freeze_schedule_with_conflict
self.client.post(self.url)
AssertionError: IntegrityError not raised
----------------------------------------------------------------------
Points to note:
create_frozen_schedule
code since the
serialization is quite long-winded and it's my understanding that the
implementation details shouldn't matter anyway since I'm mocking the
function.The purpose of the IntegrityError itself is to prevent duplicate FrozenSchedule
objects, whose Meta class looks as follows:
class Meta:
# ...
unique_together = ('client', 'data',)
Any ideas why the side effect isn't being raised?
Upvotes: 0
Views: 1098
Reputation: 117
If you want to really test that your function throws the exception, you need to test the function directly rather than through the POST. Something like:
from django.test import RequestFactory
@patch('reports.tasks.create_frozen_schedule')
def test_freeze_schedule_with_conflict(self, mock_freeze):
mock_freeze.side_effect = IntegrityError
myrequest = RequestFactory().post(*some_url*)
# you may need to add, e.g., items to myrequest.POST
with self.assertRaises(IntegrityError):@patch('reports.tasks.create_frozen_schedule')
freeze_schedule(myrequest, pk)
Upvotes: 0
Reputation: 599778
Your view catches IntegrityError and returns a redirect. The client post, which is what your test calls, doesn't raise an error at all.
Rather, you should be testing that the actions in the except block happen: is the warning set, and does the post redirect to the draft schedule instead of the frozen one.
Upvotes: 1