import json import pytest from flask import Flask, Blueprint from flask.testing import FlaskClient import flask_restx as restx class TestClient(FlaskClient): # Borrowed from https://pythonadventures.wordpress.com/2016/03/06/detect-duplicate-keys-in-a-json-file/ # Thank you to Wordpress author @ubuntuincident, aka Jabba Laci. def dict_raise_on_duplicates(self, ordered_pairs): """Reject duplicate keys.""" d = {} for k, v in ordered_pairs: if k in d: raise ValueError("duplicate key: %r" % (k,)) else: d[k] = v return d def get_json(self, url, status=200, **kwargs): response = self.get(url, **kwargs) assert response.status_code == status assert response.content_type == "application/json" return json.loads( response.data.decode("utf8"), object_pairs_hook=self.dict_raise_on_duplicates, ) def post_json(self, url, data, status=200, **kwargs): response = self.post( url, data=json.dumps(data), headers={"content-type": "application/json"} ) assert response.status_code == status assert response.content_type == "application/json" return json.loads(response.data.decode("utf8")) def get_specs(self, prefix="", status=200, **kwargs): """Get a Swagger specification for a RESTX API""" return self.get_json("{0}/swagger.json".format(prefix), status=status, **kwargs) @pytest.fixture def app(): app = Flask(__name__) app.test_client_class = TestClient yield app @pytest.fixture def api(request, app): marker = request.node.get_closest_marker("api") bpkwargs = {} kwargs = {} if marker: if "prefix" in marker.kwargs: bpkwargs["url_prefix"] = marker.kwargs.pop("prefix") if "subdomain" in marker.kwargs: bpkwargs["subdomain"] = marker.kwargs.pop("subdomain") kwargs = marker.kwargs blueprint = Blueprint("api", __name__, **bpkwargs) api = restx.Api(blueprint, **kwargs) app.register_blueprint(blueprint) yield api @pytest.fixture def mock_app(mocker): app = mocker.Mock(Flask) # mock Flask app object doesn't have any real loggers -> mock logging # set up on Api object mocker.patch.object(restx.Api, "_configure_namespace_logger") app.view_functions = {} app.extensions = {} app.config = {} return app @pytest.fixture(autouse=True) def _push_custom_request_context(request): app = request.getfixturevalue("app") options = request.node.get_closest_marker("request_context") if options is None: return ctx = app.test_request_context(*options.args, **options.kwargs) ctx.push() def teardown(): ctx.pop() request.addfinalizer(teardown)