diff --git a/django/test/utils.py b/django/test/utils.py
index 72466bec58..2f9678c29a 100644
--- a/django/test/utils.py
+++ b/django/test/utils.py
@@ -14,11 +14,10 @@ from django.core import mail
 from django.core.signals import request_started
 from django.db import reset_queries
 from django.http import request
-from django.template import Template, loader
-from django.template.loaders import cached, locmem
+from django.template import Template
+from django.template.loaders import locmem
 from django.test.signals import template_rendered, setting_changed
 from django.utils import six
-from django.utils.decorators import ContextDecorator
 from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning
 from django.utils.encoding import force_str
 from django.utils.translation import deactivate
@@ -31,7 +30,6 @@ __all__ = (
     'setup_test_environment', 'teardown_test_environment',
 )
 
-RESTORE_LOADERS_ATTR = '_original_template_source_loaders'
 TZ_SUPPORT = hasattr(time, 'tzset')
 
 
@@ -147,48 +145,6 @@ def get_runner(settings, test_runner_class=None):
     return test_runner
 
 
-class override_template_loaders(ContextDecorator):
-    """
-    Acts as a function decorator, context manager or start/end manager and
-    override the template loaders. It could be used in the following ways:
-
-    @override_template_loaders(SomeLoader())
-    def test_function(self):
-        ...
-
-    with override_template_loaders(SomeLoader(), OtherLoader()) as loaders:
-        ...
-
-    loaders = override_template_loaders.override(SomeLoader())
-    ...
-    override_template_loaders.restore()
-    """
-    def __init__(self, *loaders):
-        self.loaders = loaders
-        self.old_loaders = []
-
-    def __enter__(self):
-        self.old_loaders = loader.template_source_loaders
-        loader.template_source_loaders = self.loaders
-        return self.loaders
-
-    def __exit__(self, type, value, traceback):
-        loader.template_source_loaders = self.old_loaders
-
-    @classmethod
-    def override(cls, *loaders):
-        if hasattr(loader, RESTORE_LOADERS_ATTR):
-            raise Exception("loader.%s already exists" % RESTORE_LOADERS_ATTR)
-        setattr(loader, RESTORE_LOADERS_ATTR, loader.template_source_loaders)
-        loader.template_source_loaders = loaders
-        return loaders
-
-    @classmethod
-    def restore(cls):
-        loader.template_source_loaders = getattr(loader, RESTORE_LOADERS_ATTR)
-        delattr(loader, RESTORE_LOADERS_ATTR)
-
-
 class TestTemplateLoader(locmem.Loader):
 
     def __init__(self, *args, **kwargs):
@@ -199,46 +155,6 @@ class TestTemplateLoader(locmem.Loader):
         super(TestTemplateLoader, self).__init__(*args, **kwargs)
 
 
-class override_with_test_loader(override_template_loaders):
-    """
-    Acts as a function decorator, context manager or start/end manager and
-    override the template loaders with the test loader. It could be used in the
-    following ways:
-
-    @override_with_test_loader(templates_dict, use_cached_loader=True)
-    def test_function(self):
-        ...
-
-    with override_with_test_loader(templates_dict) as test_loader:
-        ...
-
-    test_loader = override_with_test_loader.override(templates_dict)
-    ...
-    override_with_test_loader.restore()
-    """
-
-    def __init__(self, templates_dict, use_cached_loader=False):
-        self.loader = self._get_loader(templates_dict, use_cached_loader)
-        super(override_with_test_loader, self).__init__(self.loader)
-
-    def __enter__(self):
-        return super(override_with_test_loader, self).__enter__()[0]
-
-    @classmethod
-    def override(cls, templates_dict, use_cached_loader=False):
-        loader = cls._get_loader(templates_dict, use_cached_loader)
-        return super(override_with_test_loader, cls).override(loader)[0]
-
-    @classmethod
-    def _get_loader(cls, templates_dict, use_cached_loader=False):
-        if use_cached_loader:
-            loader = cached.Loader(['django.template.loaders.locmem.Loader'])
-            loader._cached_loaders = [locmem.Loader(templates_dict)]
-            return loader
-        else:
-            return locmem.Loader(templates_dict)
-
-
 class override_settings(object):
     """
     Acts as either a decorator, or a context manager. If it's a decorator it
diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt
index fb513591a7..73c0e7a040 100644
--- a/docs/releases/1.8.txt
+++ b/docs/releases/1.8.txt
@@ -764,6 +764,10 @@ Miscellaneous
   delete a key if ``set()`` fails. This is necessary to ensure the ``cache_db``
   session store always fetches the most current session data.
 
+* Private APIs ``override_template_loaders`` and ``override_with_test_loader``
+  in ``django.test.utils`` were removed. Override ``TEMPLATE_LOADERS`` with
+  ``override_settings`` instead.
+
 .. _deprecated-features-1.8:
 
 Features deprecated in 1.8
@@ -1036,6 +1040,12 @@ class decorators. As a consequence, when overriding ``setUpClass()`` or
 ``django.template.loaders.base.Loader``. If you've written a custom template
 loader that inherits ``BaseLoader``, you must inherit ``Loader`` instead.
 
+``django.test.utils.TestTemplateLoader``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Private API ``django.test.utils.TestTemplateLoader`` is deprecated in favor of
+``django.template.loaders.locmem.Loader``.
+
 .. removed-features-1.8:
 
 Features removed in 1.8
diff --git a/tests/template_tests/tests.py b/tests/template_tests/tests.py
index 41663c678a..334dd31f7b 100644
--- a/tests/template_tests/tests.py
+++ b/tests/template_tests/tests.py
@@ -16,8 +16,7 @@ from django.template import (base as template_base, loader, Context,
     RequestContext, Template, TemplateSyntaxError)
 from django.template.loaders import app_directories, filesystem, cached
 from django.test import RequestFactory, TestCase
-from django.test.utils import (override_settings, override_template_loaders,
-                               override_with_test_loader, extend_sys_path)
+from django.test.utils import override_settings, extend_sys_path
 from django.utils.deprecation import RemovedInDjango19Warning, RemovedInDjango20Warning
 from django.utils.encoding import python_2_unicode_compatible
 from django.utils.formats import date_format
@@ -213,7 +212,7 @@ class TemplateLoaderTests(TestCase):
             test_template_sources('/DIR1/index.HTML', template_dirs,
                                   ['/DIR1/index.HTML'])
 
-    @override_template_loaders(filesystem.Loader())
+    @override_settings(TEMPLATE_LOADERS=['django.template.loaders.filesystem.Loader'])
     # Turn TEMPLATE_DEBUG on, so that the origin file name will be kept with
     # the compiled templates.
     @override_settings(TEMPLATE_DEBUG=True)
@@ -264,7 +263,7 @@ class TemplateLoaderTests(TestCase):
     # Test the base loader class via the app loader. load_template
     # from base is used by all shipped loaders excepting cached,
     # which has its own test.
-    @override_template_loaders(app_directories.Loader())
+    @override_settings(TEMPLATE_LOADERS=['django.template.loaders.app_directories.Loader'])
     def test_include_missing_template(self):
         """
         Tests that the correct template is identified as not existing
@@ -285,7 +284,7 @@ class TemplateLoaderTests(TestCase):
     # Test the base loader class via the app loader. load_template
     # from base is used by all shipped loaders excepting cached,
     # which has its own test.
-    @override_template_loaders(app_directories.Loader())
+    @override_settings(TEMPLATE_LOADERS=['django.template.loaders.app_directories.Loader'])
     def test_extends_include_missing_baseloader(self):
         """
         Tests that the correct template is identified as not existing
@@ -308,9 +307,11 @@ class TemplateLoaderTests(TestCase):
         Same as test_extends_include_missing_baseloader, only tests
         behavior of the cached loader instead of base loader.
         """
-        cache_loader = cached.Loader(('',))
-        cache_loader._cached_loaders = (app_directories.Loader(),)
-        with override_template_loaders(cache_loader,):
+        with override_settings(TEMPLATE_LOADERS=[
+            ('django.template.loaders.cached.Loader', [
+                'django.template.loaders.app_directories.Loader',
+            ]),
+        ]):
             load_name = 'test_extends_error.html'
             tmpl = loader.get_template(load_name)
             r = None
@@ -534,7 +535,11 @@ class TemplateTests(TestCase):
         template_tests.update(filter_tests)
 
         templates = dict((name, t[0]) for name, t in six.iteritems(template_tests))
-        with override_with_test_loader(templates, use_cached_loader=True) as cache_loader:
+        with override_settings(TEMPLATE_LOADERS=[
+            ('django.template.loaders.cached.Loader', [
+                ('django.template.loaders.locmem.Loader', templates),
+            ]),
+        ]):
             failures = []
             tests = sorted(template_tests.items())
 
@@ -607,7 +612,8 @@ class TemplateTests(TestCase):
                                     continue
                                 if output != result:
                                     failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s', TEMPLATE_DEBUG=%s): %s -- FAILED. Expected %r, got %r" % (is_cached, invalid_str, template_debug, name, result, output))
-                    cache_loader.reset()
+
+                    loader.template_source_loaders[0].reset()
 
                 if template_base.invalid_var_format_string:
                     expected_invalid_str = 'INVALID'
@@ -1880,15 +1886,13 @@ class TemplateTagLoading(TestCase):
 class RequestContextTests(unittest.TestCase):
 
     def setUp(self):
-        templates = {
-            'child': '{{ var|default:"none" }}',
-        }
-        override_with_test_loader.override(templates)
         self.fake_request = RequestFactory().get('/')
 
-    def tearDown(self):
-        override_with_test_loader.restore()
-
+    @override_settings(TEMPLATE_LOADERS=[
+        ('django.template.loaders.locmem.Loader', {
+            'child': '{{ var|default:"none" }}',
+        }),
+    ])
     def test_include_only(self):
         """
         Regression test for #15721, ``{% include %}`` and ``RequestContext``
diff --git a/tests/view_tests/tests/test_debug.py b/tests/view_tests/tests/test_debug.py
index e50a29f1d1..b9987c72b0 100644
--- a/tests/view_tests/tests/test_debug.py
+++ b/tests/view_tests/tests/test_debug.py
@@ -17,7 +17,6 @@ from django.core.files.uploadedfile import SimpleUploadedFile
 from django.core.urlresolvers import reverse
 from django.template.base import TemplateDoesNotExist
 from django.test import TestCase, RequestFactory, override_settings
-from django.test.utils import override_with_test_loader
 from django.utils.encoding import force_text, force_bytes
 from django.utils import six
 from django.views.debug import CallableSettingWrapper, ExceptionReporter
@@ -66,14 +65,17 @@ class DebugViewTests(TestCase):
 
     def test_403(self):
         # Ensure no 403.html template exists to test the default case.
-        with override_with_test_loader({}):
+        with override_settings(TEMPLATE_LOADERS=[]):
             response = self.client.get('/raises403/')
             self.assertContains(response, '<h1>403 Forbidden</h1>', status_code=403)
 
     def test_403_template(self):
         # Set up a test 403.html template.
-        with override_with_test_loader({'403.html': 'This is a test template '
-                                        'for a 403 Forbidden error.'}):
+        with override_settings(TEMPLATE_LOADERS=[
+            ('django.template.loaders.locmem.Loader', {
+                '403.html': 'This is a test template for a 403 Forbidden error.',
+            })
+        ]):
             response = self.client.get('/raises403/')
             self.assertContains(response, 'test template', status_code=403)
 
diff --git a/tests/view_tests/tests/test_defaults.py b/tests/view_tests/tests/test_defaults.py
index 1f6a554c19..6a3a495c23 100644
--- a/tests/view_tests/tests/test_defaults.py
+++ b/tests/view_tests/tests/test_defaults.py
@@ -1,7 +1,7 @@
 from __future__ import unicode_literals
 
 from django.test import TestCase
-from django.test.utils import override_settings, override_with_test_loader
+from django.test.utils import override_settings
 
 from ..models import UrlArticle
 
@@ -40,9 +40,12 @@ class DefaultsTests(TestCase):
         Test that 404.html and 500.html templates are picked by their respective
         handler.
         """
-        with override_with_test_loader({
+        with override_settings(TEMPLATE_LOADERS=[
+            ('django.template.loaders.locmem.Loader', {
                 '404.html': 'This is a test template for a 404 error.',
-                '500.html': 'This is a test template for a 500 error.'}):
+                '500.html': 'This is a test template for a 500 error.',
+            }),
+        ]):
             for code, url in ((404, '/non_existing_url/'), (500, '/server_error/')):
                 response = self.client.get(url)
                 self.assertContains(response, "test template for a %d error" % code,