44

I am relatively new to Python and want to use a assertRaises test to check for a ValidationError, which works ok. However, I have many ValidationErrors and I want to make sure the right one is returned. I figured I could pass something into assertRaises but it doesn't look like I can, so I figured I would just do an assertTrue and check the exception message. However, I don't know how to access it. Is this even a good way to approach this issue? thanks.

class DailyEntriesTests(TestCase):
def test_cant_have_ip_and_user(self):
    u = createUser(False)
    de = createDailyEntry(u, "1.1.1.1", 1)
    with self.assertRaises(ValidationError) as cm:
        de.full_clean()

    # this line bombs - message doesn't exist. I also tried "error_code" like I saw in the documentation, but that doesn't work
    print(cm.exception.message)

    self.assertTrue(cm.exception.message.contains("Both"))
0

3 Answers 3

51

You can just use assertRaisesRegexp.

with self.assertRaisesRegexp(ValidationError, "Both"):
    de.full_clean()

When you use it as a context manager the 2nd argument is a regular expression to search through the exception's string representation.

Sign up to request clarification or add additional context in comments.

1 Comment

I just feel sorry for myself that this post is from 2014 and I never knew about this until now 🙈😅
32

Since the question is related to Django, you could also use the assertRaisesMessage context manager when inheriting from django's TestCase.

from django.test import TestCase

class ExceptionTest(TestCase):

    def test_call_raises_exception_with_custom_message(self):
        with self.assertRaisesMessage(Exception, 'My custom message!'):
            call_that_causes_exception()
    

Note: The assertRaisesMessage manager does an in lookup on the exceptions message: Say your exception raises "My custom message!", asserting for "custom message" passes. Bear this in mind especially if you have multiple (custom) exceptions with similar messages.

(E.g. two different exceptions raising "My custom message! Further details..." and "My custom message! No details." would both pass an assert for "My custom message!").

Comments

17

Nowadays you can use assertRaises as a context manager. This way you can capture the exception and inspect it later.

with self.assertRaises(SomeException) as cm:
    do_something()

the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)

3 Comments

this gave me the following error: '_AssertRaisesContext' object has no attribute 'message'
I just tested and it is working fine with CPython 3.6.4
If you want to test the message, you can do something like: self.assertEqual('{}'.format(cm.exception), 'I expected this message')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.