From 7fa1dd8a80795d7573fe650014c5d23af7557bc7 Mon Sep 17 00:00:00 2001
From: pscottdevos <scott.devos@sykes.com>
Date: Fri, 7 Aug 2015 14:28:54 -0500
Subject: [PATCH] Fixed #25163 -- Fixed exception handling in nested test
 client requests.

---
 django/test/client.py      |  6 +++---
 tests/test_client/tests.py |  8 ++++++++
 tests/test_client/urls.py  |  1 +
 tests/test_client/views.py | 11 +++++++++++
 4 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/django/test/client.py b/django/test/client.py
index 945fa13281..8d46ea629a 100644
--- a/django/test/client.py
+++ b/django/test/client.py
@@ -442,9 +442,9 @@ class Client(RequestFactory):
         signal_uid = "template-render-%s" % id(request)
         signals.template_rendered.connect(on_template_render, dispatch_uid=signal_uid)
         # Capture exceptions created by the handler.
-        got_request_exception.connect(self.store_exc_info, dispatch_uid="request-exception")
+        exception_uid = "request-exception-%s" % id(request)
+        got_request_exception.connect(self.store_exc_info, dispatch_uid=exception_uid)
         try:
-
             try:
                 response = self.handler(environ)
             except TemplateDoesNotExist as e:
@@ -493,7 +493,7 @@ class Client(RequestFactory):
             return response
         finally:
             signals.template_rendered.disconnect(dispatch_uid=signal_uid)
-            got_request_exception.disconnect(dispatch_uid="request-exception")
+            got_request_exception.disconnect(dispatch_uid=exception_uid)
 
     def get(self, path, data=None, follow=False, secure=False, **extra):
         """
diff --git a/tests/test_client/tests.py b/tests/test_client/tests.py
index ae70f5c494..042633ad54 100644
--- a/tests/test_client/tests.py
+++ b/tests/test_client/tests.py
@@ -640,6 +640,14 @@ class ClientTest(TestCase):
         self.assertEqual(mail.outbox[1].to[0], 'second@example.com')
         self.assertEqual(mail.outbox[1].to[1], 'third@example.com')
 
+    def test_exception_following_nested_client_request(self):
+        """
+        A nested test client request shouldn't clobber exception signals from
+        the outer client request.
+        """
+        with self.assertRaisesMessage(Exception, 'exception message'):
+            self.client.get('/nesting_exception_view/')
+
 
 @override_settings(
     MIDDLEWARE_CLASSES=['django.middleware.csrf.CsrfViewMiddleware'],
diff --git a/tests/test_client/urls.py b/tests/test_client/urls.py
index 1b7530db1c..f605448b5b 100644
--- a/tests/test_client/urls.py
+++ b/tests/test_client/urls.py
@@ -31,6 +31,7 @@ urlpatterns = [
     url(r'^broken_view/$', views.broken_view),
     url(r'^mail_sending_view/$', views.mail_sending_view),
     url(r'^mass_mail_sending_view/$', views.mass_mail_sending_view),
+    url(r'^nesting_exception_view/$', views.nesting_exception_view),
     url(r'^django_project_redirect/$', views.django_project_redirect),
 
     url(r'^accounts/login/$', auth_views.login, {'template_name': 'login.html'}),
diff --git a/tests/test_client/views.py b/tests/test_client/views.py
index f26d474612..070e6305c2 100644
--- a/tests/test_client/views.py
+++ b/tests/test_client/views.py
@@ -11,6 +11,7 @@ from django.http import (
 )
 from django.shortcuts import render_to_response
 from django.template import Context, Template
+from django.test import Client
 from django.utils.decorators import method_decorator
 from django.utils.six.moves.urllib.parse import urlencode
 
@@ -309,5 +310,15 @@ def mass_mail_sending_view(request):
     return HttpResponse("Mail sent")
 
 
+def nesting_exception_view(request):
+    """
+    A view that uses a nested client to call another view and then raises an
+    exception.
+    """
+    client = Client()
+    client.get('/get_view/')
+    raise Exception('exception message')
+
+
 def django_project_redirect(request):
     return HttpResponseRedirect('https://www.djangoproject.com/')