Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client: testing exceptions in views (client.store_exc_info) #130

Open
blueyed opened this issue Jul 11, 2014 · 4 comments
Open

Client: testing exceptions in views (client.store_exc_info) #130

blueyed opened this issue Jul 11, 2014 · 4 comments

Comments

@blueyed
Copy link
Contributor

blueyed commented Jul 11, 2014

I want to test a view that throws an exception, and came up with the following code to make it work, so that the exception is not re-thrown by the client (code ref: https://github.com/django/django/blob/master/django/test/client.py#L421-443):

def test_foo(client):
    def store_exc_info(*args, **kwargs):
        pass
    # client.store_exc_info = lambda *args, **kwargs: True
    client.store_exc_info = store_exc_info

    client.get('/raises-500')

Given that it was not trivial to figure this out I wonder if this is the correct approach and if pytest-django could help in this regard (documentation, helper, ...)

I will look into providing a documentation update for Django itself, but want to get some feedback first.

@pelme
Copy link
Member

pelme commented Jul 11, 2014

Are you looking to silence that exception? Or catch it? Would you like that test to fail?

@blueyed
Copy link
Contributor Author

blueyed commented Jul 11, 2014

I want to get the rendered content of the page, not the Exception (IndexError) from the view.

It's related to this commit in Django: django/django@f9cdde0cb4

E.g.:

from django.conf.urls import patterns, url
from config.urls import urlpatterns as config_urls
from django.views.debug import CLEANSED_SUBSTITUTE

class MockUrlConf500():
    urlpatterns = config_urls \
        + patterns('', url(r'^500$', lambda x: [][0]))

@mock.patch('django.core.handlers.base.logger')
@pytest.mark.urls(urls=MockUrlConf500)
def test_technical_500(mock_logger, live_server, client, submitter_client, admin_client,
                       settings):
    # Prevent the client from re-raising the exception.
    # Related to this commit: https://github.com/django/django/commit/f9cdde0cb4
    client.store_exc_info = lambda *args, **kwargs: True

    from django.template.loader import render_to_string
    pretty_template = render_to_string('500.html')  # via CustomErrorHandler
    mark_technical_500 = '<pre class="exception_value">'

    settings.DEBUG = True
    response = client.get('/500')
    assert response.status_code == 500
    assert response.content != pretty_template
    assert mark_technical_500 in response.content
    assert "because you have <code>DEBUG = True</code>" in response.content
    assert CLEANSED_SUBSTITUTE in response.content
    assert settings.SECRET_KEY not in response.content
    assert mock_logger.error.call_count == 1

@dieselmachine
Copy link

You are a hero for figuring this out. I've been struggling for hours trying to figure out how to test django-tastypie's canned_response, and the django test client interfered with the test (as I'm sure you know). Your solution completely solved the problem, thank you so much! You are awesome!

Also, anyone who considers this interference by the test client to be a "feature" should be ashamed of themselves.

@pelme
Copy link
Member

pelme commented Sep 24, 2015

I think a "fix" for this belongs in Django and in the test Client itself. I.e. initiating client objects with client = Client(raise_view_exceptions=False) or something like that seems like the proper way to handle this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants