You can use unittest.mock to do it. You should patch Books.objects object by patch.object and use side_effect to raise exception. A complete test of your method exception behavior should be:
import unittest
from unittest.mock import patch, ANY
from django.test.client import RequestFactory
class TestDjango(unittest.TestCase):
@patch("your_module.messages")
@patch("your_module.HttpResponseRedirect")
def test_get_books_exception(self,mock_redirect,mock_messages)
r = RequestFactory().get('/I_dont_konw_how_to_build_your_request/')
objs = Books.objects
with patch.object(objs,"get_or_create", side_effect=Exception()):
self.assertIs(get_books(r),mock_redirect.return_value)
mock_messages.error.assert_called_with(r, ANY)
mock_redirect.assert_called_with(reverse('my_books'))
I used ANY do remove the string dependency. I'm not sure what you want test in your code (complete behavior or just redirect...), anyway I wrote a complete example.
If your project is not a legacy work consider to rewrite your method (and the new django's ORM calls) in TDD style where you have for instance a _get_books_proxy() function that just call the django ORM methods:
def _get_books_proxy(request):
return Books.objects.get_or_create(user=request.user)
and now patch _get_books_proxy() directly by patch decorator as:
@patch("your_module.messages")
@patch("your_module.HttpResponseRedirect")
@patch("your_module._get_books_proxy", side_effect=Exception())
def test_get_books_exception(self,mock_get_book, mock_redirect, mock_messages)
r = RequestFactory().get('/I_dont_konw_how_to_build_your_request/')
self.assertIs(get_books(r),mock_redirect.return_value)
mock_messages.error.assert_called_with(r, ANY)
mock_redirect.assert_called_with(reverse('my_books'))
Moreover _get_books_proxy() behavior can be tested by patching Books and passing a simple Mock():
@patch("your_module.Books")
def test__get_books_proxy(self,mock_books):
r = Mock()
self.assertIs(mock_books.objects.get_or_create.return_value, your_module._get_books_proxy(r))
mock_books.objects.get_or_create.assert_called_with(user=r.user)
Now you have a sentinel that can yield to you if your critical point behavior will be changed.
I apologize if you find some errors (I cannot test it)... but I hope the idea is clear.
ForeignKeyforBooksto have a uniqueuservalue?try/exceptblocks and I can't injectraisesto the view code every time I want to test. Well, maybe that could be done, but it won't be elegant. PS this question is there a general solution for unit testing; not only this specific example I provided.