Get IP Address when testing flask application through nosetests
Asked Answered
A

3

21

My application depends on request.remote_addr which is None when i run tests through nosetests which uses app.test_client().post('/users/login', ....).

How can I emulate an IP (127.0.0.1 works fine) when I run tests? I've tried setting environment variables, sent in headers with the post() method and I've digged through nosetests, werkzeugs and flasks documentation but nothing I've tried has worked.

Antilepton answered 14/2, 2013 at 10:35 Comment(3)
Possible duplicate of Setting (mocking) request headers for Flask app unit testLiv
@Styvane: Uhm, this question is a month older, how is it a duplicate?Antilepton
Perhaps I didn't choose the right question but yes it is possibleLiv
S
27

You can set options for the underlying Werkzeug environment using environ_base:

from flask import Flask, request
import unittest

app = Flask(__name__)
app.debug = True
app.testing = True

@app.route('/')
def index():
    return str(request.remote_addr)

class TestApp(unittest.TestCase):

    def test_remote_addr(self):
        c = app.test_client()
        resp = c.get('/', environ_base={'REMOTE_ADDR': '127.0.0.1'})
        self.assertEqual('127.0.0.1', resp.data)


if __name__ == '__main__':
    unittest.main()
Sino answered 14/2, 2013 at 10:46 Comment(3)
Thanks, it works perfectly but having to append that on every single call would get tedious. A friend gave me a solution for fix that changes every call. Posting it as an answer as well.Antilepton
+1 This appears to be the way werkzeug intended you to do this and was exactly what I was looking forMatthaeus
Now my tests are passing in instances that needs to have a valid IP. Thanks.Bedlamite
A
8

A friend gave me this solution, which works across all requests:

class myProxyHack(object):

    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        environ['REMOTE_ADDR'] = environ.get('REMOTE_ADDR', '127.0.0.1')
        return self.app(environ, start_response)

app.wsgi_app = myProxyHack(app.wsgi_app)

app.test_client().post(...)
Antilepton answered 14/2, 2013 at 10:54 Comment(0)
G
0

You can also pass a header param to the test_request_context if you prefer.

Example:

from flask import Flask, request
import unittest

app = Flask(__name__)
app.debug = True
app.testing = True

@app.route('/')
def index():
    return str(request.remote_addr)

class TestApp(unittest.TestCase):

    def test_headers(self):
        user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0"
        ip_address = 127.0.0.1
        headers = {
            'Remote_Addr': ip_address,
            'User_Agent': user_agent
        }

        with self.test_request_context(headers=headers):
            # Do something
            pass

This is useful when you need to perform several unit tests using the request object in other modules.

See the test_request_context documentation.

Greenockite answered 22/7, 2019 at 15:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.