def test_incorrect_content_length(custom_content_length: str) -> None: """ Custom content length headers are passed through to the Flask endpoint. """ app = Flask(__name__) data = b'12345' @app.route('/', methods=['POST']) def _() -> str: request.environ['wsgi.input_terminated'] = True assert len(data) == len(request.data) assert request.headers['Content-Length'] == custom_content_length return '' test_client = app.test_client() environ_builder = werkzeug.test.EnvironBuilder( path='/', method='POST', data=b'12345', ) environ = environ_builder.get_environ() environ['CONTENT_LENGTH'] = custom_content_length response = test_client.open(environ) expected_status_code = 200 assert response.status_code == expected_status_code requests_request = requests.Request( method='POST', url='http://www.example.com/', data=data, ).prepare() requests_request.headers['Content-Length'] = custom_content_length with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) session = requests.Session() responses_response = session.send(request=requests_request) assert responses_response.status_code == expected_status_code with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) session = requests.Session() req_mock_response = session.send(request=requests_request) assert req_mock_response.status_code == expected_status_code
def test_request_needs_data() -> None: """ Routes which require data are supported. """ app = Flask(__name__) @app.route('/') @consumes('application/json') def _() -> str: return str(request.get_json()['hello']) test_client = app.test_client() response = test_client.get( '/', content_type='application/json', data=json.dumps({'hello': 'world'}), ) expected_status_code = 200 expected_content_type = 'text/html; charset=utf-8' expected_data = b'world' assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert response.data == expected_data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.get( 'http://www.example.com', headers={'Content-Type': 'application/json'}, data=json.dumps({'hello': 'world'}), ) assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert responses_response.text == expected_data.decode() with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.get( 'http://www.example.com', headers={'Content-Type': 'application/json'}, data=json.dumps({'hello': 'world'}), ) assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert req_mock_response.text == expected_data.decode()
def test_multiple_functions_same_path_different_type() -> None: """ When multiple functions exist with the same path but have a different type, the mock matches them just the same. """ app = Flask(__name__) @app.route('/<my_variable>') def _(_: float) -> str: ... # pragma: no cover @app.route('/<int:my_variable>') def ___(my_variable: int) -> str: return 'Is int: ' + str(my_variable) @app.route('/<string:my_variable>') def ____(_: str) -> str: ... # pragma: no cover test_client = app.test_client() response = test_client.get('/4') expected_status_code = 200 expected_content_type = 'text/html; charset=utf-8' expected_data = b'Is int: 4' assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert response.data == expected_data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.get('http://www.example.com/4') assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert responses_response.text == expected_data.decode() with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.get('http://www.example.com/4') assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert req_mock_response.text == expected_data.decode()
def test_headers() -> None: """ Request headers are sent. """ app = Flask(__name__) @app.route('/') def _() -> str: assert 'Content-Type' not in request.headers assert request.headers['hello'] == 'world' return 'Hello, World!' test_client = app.test_client() response = test_client.get('/', headers={'hello': 'world'}) expected_status_code = 200 expected_content_type = 'text/html; charset=utf-8' expected_data = b'Hello, World!' assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert response.data == expected_data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.get( 'http://www.example.com', headers={'hello': 'world'}, ) assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert responses_response.text == expected_data.decode() with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.get( 'http://www.example.com', headers={'hello': 'world'}, ) assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert req_mock_response.text == expected_data.decode()
def test_route_with_uuid_variable() -> None: """ A route with a uuid variable works. """ app = Flask(__name__) @app.route('/<uuid:my_variable>') def _(my_variable: uuid.UUID) -> str: return 'Hello: ' + my_variable.hex test_client = app.test_client() random_uuid = uuid.uuid4() response = test_client.get(f'/{random_uuid}') expected_status_code = 200 expected_content_type = 'text/html; charset=utf-8' expected_data = bytes(f'Hello: {random_uuid.hex}', 'utf-8') assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert response.data == expected_data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.get( f'http://www.example.com/{random_uuid}', ) assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert responses_response.text == expected_data.decode() with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.get( f'http://www.example.com/{random_uuid}', ) assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert req_mock_response.text == expected_data.decode()
def test_query_string() -> None: """ Query strings work. """ app = Flask(__name__) @app.route('/') def _() -> str: result = request.args['frasier'] return 'Hello: ' + str(result) test_client = app.test_client() response = test_client.get('/?frasier=crane') expected_status_code = 200 expected_content_type = 'text/html; charset=utf-8' expected_data = b'Hello: crane' assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert response.data == expected_data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.get( 'http://www.example.com?frasier=crane', ) assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert responses_response.text == expected_data.decode() with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.get( 'http://www.example.com?frasier=crane', ) assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert req_mock_response.text == expected_data.decode()
def test_nested_path() -> None: """ A route with a variable nested in a path works. """ app = Flask(__name__) @app.route('/users/<int:my_variable>/posts') def _(my_variable: int) -> str: return 'Posts for: ' + str(my_variable) test_client = app.test_client() response = test_client.get('/users/4/posts') expected_status_code = 200 expected_content_type = 'text/html; charset=utf-8' expected_data = b'Posts for: 4' assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert response.data == expected_data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.get( 'http://www.example.com/users/4/posts', ) assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert responses_response.text == expected_data.decode() with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.get( 'http://www.example.com/users/4/posts', ) assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert req_mock_response.text == expected_data.decode()
def test_route_with_multiple_variables() -> None: """ A route with multiple variables works. """ app = Flask(__name__) @app.route('/users/<string:my_org>/<string:my_user>/posts') def _(my_org: str, my_user: str) -> str: return 'Posts for: ' + my_org + '/' + my_user test_client = app.test_client() response = test_client.get('/users/cranes/frasier/posts') expected_status_code = 200 expected_content_type = 'text/html; charset=utf-8' expected_data = b'Posts for: cranes/frasier' assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert response.data == expected_data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.get( 'http://www.example.com/users/cranes/frasier/posts', ) assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert responses_response.text == expected_data.decode() with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.get( 'http://www.example.com/users/cranes/frasier/posts', ) assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert req_mock_response.text == expected_data.decode()
def test_route_with_json() -> None: """ A route that returns JSON data works. """ app = Flask(__name__) @app.route('/') def _() -> Tuple[Response, int]: return jsonify({'hello': 'world'}), 201 test_client = app.test_client() response = test_client.get('/') expected_status_code = 201 expected_content_type = 'application/json' expected_json = {'hello': 'world'} assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert response.json == expected_json with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.get('http://www.example.com') assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert responses_response.json() == expected_json with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.get('http://www.example.com') assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert req_mock_response.json() == expected_json
def test_route_with_path_variable_with_slash() -> None: """ A route with a path variable works. """ app = Flask(__name__) @app.route('/<path:my_variable>') def _(my_variable: str) -> str: return 'Hello: ' + my_variable test_client = app.test_client() response = test_client.get('/foo/bar') expected_status_code = 200 expected_content_type = 'text/html; charset=utf-8' expected_data = b'Hello: foo/bar' assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert response.data == expected_data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.get('http://www.example.com/foo/bar') assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert responses_response.text == expected_data.decode() with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.get('http://www.example.com/foo/bar') assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert req_mock_response.text == expected_data.decode()
def test_post_verb() -> None: """ A route with the POST verb works. """ app = Flask(__name__) @app.route('/', methods=['POST']) def _() -> str: return 'Hello, World!' test_client = app.test_client() response = test_client.post('/') expected_status_code = 200 expected_content_type = 'text/html; charset=utf-8' expected_data = b'Hello, World!' assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert response.data == expected_data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.post('http://www.example.com/') assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert responses_response.text == expected_data.decode() with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.post('http://www.example.com/') assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert req_mock_response.text == expected_data.decode()
def test_wrong_type_given() -> None: """ A route with the wrong type given works. """ app = Flask(__name__) @app.route('/<int:my_variable>') def _(_: int) -> str: ... # pragma: no cover test_client = app.test_client() response = test_client.get('/a') expected_status_code = 404 expected_content_type = 'text/html; charset=utf-8' assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert b'not found on the server' in response.data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.get('http://www.example.com/a') assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert 'not found on the server' in responses_response.text with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.get('http://www.example.com/a') assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert 'not found on the server' in req_mock_response.text
def test_decorator(self) -> None: """ It is possible to use the helper with a ``responses`` decorator. """ app = Flask(__name__) @app.route('/') def _() -> str: return 'Hello, World!' add_flask_app_to_mock( mock_obj=responses, flask_app=app, base_url='http://www.example.com', ) response = requests.get('http://www.example.com') assert response.status_code == 200 assert response.text == 'Hello, World!'
def enable_requests_mock( monkeypatch: MonkeyPatch, requests_mock: Mocker, ) -> None: """ Enable a mock service backed by the Flask applications. """ add_flask_app_to_mock( mock_obj=requests_mock, flask_app=VWS_FLASK_APP, base_url='https://vws.vuforia.com', ) add_flask_app_to_mock( mock_obj=requests_mock, flask_app=CLOUDRECO_FLASK_APP, base_url='https://cloudreco.vuforia.com', ) add_flask_app_to_mock( mock_obj=requests_mock, flask_app=TARGET_MANAGER_FLASK_APP, base_url=_EXAMPLE_URL_FOR_TARGET_MANAGER, ) monkeypatch.setenv( name='TARGET_MANAGER_BASE_URL', value=_EXAMPLE_URL_FOR_TARGET_MANAGER, )
def test_404_no_such_method() -> None: """ A route with the wrong method given works. """ app = Flask(__name__) @app.route('/') def _() -> str: ... # pragma: no cover test_client = app.test_client() response = test_client.post('/') expected_status_code = 405 expected_content_type = 'text/html; charset=utf-8' assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert b'not allowed for the requested URL.' in response.data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) with pytest.raises(requests.exceptions.ConnectionError): requests.post('http://www.example.com/') with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) with pytest.raises(requests_mock.exceptions.NoMockAddress): requests.post('http://www.example.com/')
def test_context_manager(self) -> None: """ It is possible to use the helper with a ``requests_mock`` context manager. """ app = Flask(__name__) @app.route('/') def _() -> str: return 'Hello, World!' with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) response = requests.get('http://www.example.com') assert response.status_code == 200 assert response.text == 'Hello, World!'
def test_fixture( # pylint: disable=redefined-outer-name self, requests_mock: requests_mock.Mocker, ) -> None: """ It is possible to use the helper with a ``requests_mock`` fixture. """ app = Flask(__name__) @app.route('/') def _() -> str: return 'Hello, World!' add_flask_app_to_mock( mock_obj=requests_mock, flask_app=app, base_url='http://www.example.com', ) response = requests.get('http://www.example.com') assert response.status_code == 200
def test_adapter(self) -> None: """ It is possible to use the helper with a ``requests_mock`` fixture. """ app = Flask(__name__) @app.route('/') def _() -> str: return 'Hello, World!' session = requests.Session() adapter = requests_mock.Adapter() session.mount('mock', adapter) add_flask_app_to_mock( mock_obj=adapter, flask_app=app, base_url='mock://www.example.com', ) response = session.get('mock://www.example.com') assert response.status_code == 200 assert response.text == 'Hello, World!'
def _enable_use_docker_in_memory( working_database: VuforiaDatabase, inactive_database: VuforiaDatabase, monkeypatch: MonkeyPatch, ) -> Generator: # We set ``wsgi.input_terminated`` to ``True`` so that when going through # ``requests``, the Flask applications # have the given ``Content-Length`` headers and the given data in # ``request.headers`` and ``request.data``. # # We do not set these in the Flask application itself. # This is because when running the Flask application, if this is set, # reading ``request.data`` hangs. # # Therefore, when running the real Flask application, the behavior is not # the same as the real Vuforia. # This is documented as a difference in the documentation for this package. VWS_FLASK_APP.config['TERMINATE_WSGI_INPUT'] = True CLOUDRECO_FLASK_APP.config['TERMINATE_WSGI_INPUT'] = True target_manager_base_url = 'http://example.com' monkeypatch.setenv( name='TARGET_MANAGER_BASE_URL', value=target_manager_base_url, ) with requests_mock.Mocker(real_http=False) as mock: add_flask_app_to_mock( mock_obj=mock, flask_app=VWS_FLASK_APP, base_url='https://vws.vuforia.com', ) add_flask_app_to_mock( mock_obj=mock, flask_app=CLOUDRECO_FLASK_APP, base_url='https://cloudreco.vuforia.com', ) add_flask_app_to_mock( mock_obj=mock, flask_app=TARGET_MANAGER_FLASK_APP, base_url=target_manager_base_url, ) databases_url = target_manager_base_url + '/databases' databases = requests.get(url=databases_url).json() for database in databases: database_name = database['database_name'] requests.delete(url=databases_url + '/' + database_name) requests.post(url=databases_url, json=working_database.to_dict()) requests.post(url=databases_url, json=inactive_database.to_dict()) yield
def test_cookies() -> None: """ Cookies work. """ app = Flask(__name__) @app.route('/', methods=['POST']) def _() -> Response: response = make_response() response.set_cookie('frasier_set', 'crane_set') assert request.cookies['frasier'] == 'crane' assert request.cookies['frasier2'] == 'crane2' response.data = 'Hello, World!' assert isinstance(response, Response) return response test_client = app.test_client() test_client.set_cookie(server_name='', key='frasier', value='crane') test_client.set_cookie(server_name='', key='frasier2', value='crane2') original_cookies = set(test_client.cookie_jar) response = test_client.post('/') expected_status_code = 200 expected_content_type = 'text/html; charset=utf-8' expected_data = b'Hello, World!' (new_cookie,) = set(test_client.cookie_jar) - original_cookies assert new_cookie.name == 'frasier_set' assert new_cookie.value == 'crane_set' assert response.status_code == expected_status_code assert response.headers['Content-Type'] == expected_content_type assert response.data == expected_data with responses.RequestsMock(assert_all_requests_are_fired=False) as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) responses_response = requests.post( 'http://www.example.com', cookies={ 'frasier': 'crane', 'frasier2': 'crane2', }, ) assert responses_response.status_code == expected_status_code assert responses_response.headers['Content-Type'] == expected_content_type assert responses_response.text == expected_data.decode() assert responses_response.cookies['frasier_set'] == 'crane_set' with requests_mock.Mocker() as resp_m: add_flask_app_to_mock( mock_obj=resp_m, flask_app=app, base_url='http://www.example.com', ) req_mock_response = requests.post( 'http://www.example.com', cookies={ 'frasier': 'crane', 'frasier2': 'crane2', }, ) assert req_mock_response.status_code == expected_status_code assert req_mock_response.headers['Content-Type'] == expected_content_type assert req_mock_response.text == expected_data.decode() assert req_mock_response.cookies['frasier_set'] == 'crane_set'