Default environ
diff --git a/CHANGES b/CHANGES
index 5a1f5a3334..13ce156c22 100644
--- a/CHANGES
+++ b/CHANGES
@@ -19,6 +19,8 @@ Version 0.12
   well as error handlers.
 - Disable logger propagation by default for the app logger.
 - Add support for range requests in ``send_file``.
+- ``app.test_client`` includes preset default environment, which can now be
+  directly set, instead of per ``client.get``.
 
 Version 0.11.2
 --------------
diff --git a/flask/testing.py b/flask/testing.py
index 8eacf58b40..3160024565 100644
--- a/flask/testing.py
+++ b/flask/testing.py
@@ -10,6 +10,7 @@
     :license: BSD, see LICENSE for more details.
 """
 
+import werkzeug
 from contextlib import contextmanager
 from werkzeug.test import Client, EnvironBuilder
 from flask import _request_ctx_stack
@@ -43,11 +44,23 @@ class FlaskClient(Client):
     information about how to use this class refer to
     :class:`werkzeug.test.Client`.
 
+    .. versionchanged:: 0.12
+       `app.test_client()` includes preset default environment, which can be
+       set after instantiation of the `app.test_client()` object in
+       `client.environ_base`.
+
     Basic usage is outlined in the :ref:`testing` chapter.
     """
 
     preserve_context = False
 
+    def __init__(self, *args, **kwargs):
+        super(FlaskClient, self).__init__(*args, **kwargs)
+        self.environ_base = {
+            "REMOTE_ADDR": "127.0.0.1",
+            "HTTP_USER_AGENT": "werkzeug/" + werkzeug.__version__
+        }
+
     @contextmanager
     def session_transaction(self, *args, **kwargs):
         """When used in combination with a ``with`` statement this opens a
@@ -101,6 +114,7 @@ def session_transaction(self, *args, **kwargs):
     def open(self, *args, **kwargs):
         kwargs.setdefault('environ_overrides', {}) \
             ['flask._preserve_context'] = self.preserve_context
+        kwargs.setdefault('environ_base', self.environ_base)
 
         as_tuple = kwargs.pop('as_tuple', False)
         buffered = kwargs.pop('buffered', False)
diff --git a/tests/test_testing.py b/tests/test_testing.py
index 7bb99e7971..9d3539049d 100644
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -11,6 +11,7 @@
 import pytest
 
 import flask
+import werkzeug
 
 from flask._compat import text_type
 
@@ -43,6 +44,40 @@ def index():
         rv = c.get('/')
         assert rv.data == b'http://localhost/'
 
+def test_environ_base_default():
+    app = flask.Flask(__name__)
+    app.testing = True
+    @app.route('/')
+    def index():
+        flask.g.user_agent = flask.request.headers["User-Agent"]
+        return flask.request.remote_addr
+
+    with app.test_client() as c:
+        rv = c.get('/')
+        assert rv.data == b'127.0.0.1'
+        assert flask.g.user_agent == 'werkzeug/' + werkzeug.__version__
+
+def test_environ_base_modified():
+    app = flask.Flask(__name__)
+    app.testing = True
+    @app.route('/')
+    def index():
+        flask.g.user_agent = flask.request.headers["User-Agent"]
+        return flask.request.remote_addr
+
+    with app.test_client() as c:
+        c.environ_base['REMOTE_ADDR'] = '0.0.0.0'
+        c.environ_base['HTTP_USER_AGENT'] = 'Foo'
+        rv = c.get('/')
+        assert rv.data == b'0.0.0.0'
+        assert flask.g.user_agent == 'Foo'
+
+        c.environ_base['REMOTE_ADDR'] = '0.0.0.1'
+        c.environ_base['HTTP_USER_AGENT'] = 'Bar'
+        rv = c.get('/')
+        assert rv.data == b'0.0.0.1'
+        assert flask.g.user_agent == 'Bar'
+
 def test_redirect_keep_session():
     app = flask.Flask(__name__)
     app.secret_key = 'testing'

Addresses #1467. Now you can pass `environ_base` dictionary into `app.test_client`. This also allows overriding per `open` call (or `make_test_environ_builder` call).

Perhaps a better solution would be to edit werkzeug directly and add it to that init (which, in turn, would allow us to remove the subclass init). I don't believe that would cause any unintended behavior, but I'm open to further conversation on it.

<!-- Reviewable:start -->

---

This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/pallets/flask/2047)

<!-- Reviewable:end -->
