pytest_flask.plugin.JSONResponse PicklingError
crazygit opened this issue · comments
The app code
from flask import Flask,jsonify
from flask_caching import Cache
CACHE_TYPE = 'redis'
CACHE_KEY_PREFIX = 'caches:'
CACHE_REDIS_URL = 'redis://localhost:8888/0'
DEBUG = True
CACHE_DEFAULT_TIMEOUT = 5 * 60 # seconds
app = Flask(__name__)
app.config.from_object(__name__)
cache = Cache(app)
@app.route('/')
@cache.cached(query_string=True)
def index():
return jsonify({"message": "Hello world"})
if __name__ == '__main__':
app.run()
when test with pytest_flask
from flask import url_for
def test_get_index(client):
assert client.get(url_for('index')).status_code == 200
the error output
_pickle.PicklingError: Can't pickle <class 'pytest_flask.plugin.<class 'pytest_flask.plugin.JSONResponse'>'>: attribute lookup <class 'pytest_flask.plugin.JSONResponse'> on pytest_flask.plugin failed
When debug the error, I found the error was caused by pytest_flask dynamic changed the Flask Response in pytest_flask/plugin.py
with type
.
def _make_test_response_class(response_class):
"""Extends the response class with special attribute to test JSON
responses. Don't override user-defined `json` attribute if any.
:param response_class: An original response class.
"""
if 'json' in response_class.__dict__:
return response_class
return type(str(JSONResponse), (response_class, JSONResponse), {})
But I don't kwon how to fix this issure. Any suggestion on pickle dynamic class ?
I ran into the same issue. I was able to get farther by setting up a response class that has its own implementation of the json
property. That keeps pytest_flask from trying to replace the class at runtime.
from flask import json, Response
class TestingResponse(Response):
@property
def json(self):
return json.loads(self.data)
@pytest.fixture(scope="session")
def app(session_schema):
app = create_app()
app.response_class = TestingResponse
return app
Compared to pytest_flask's JSONResponse, this doesn't cache the json and it doesn't override __eq__
and __ne__
. (I haven't really dug into the implications, but this seems to fix my problem.)
@crazygit, @ianmclaury Thanks for documenting the issue and providing a solution so others facing the same problem can find it.
The provided example works fine on my environment
macOS Catalina
python 3.7.8
pytest==6.1.0
pytest-cache==1.0
Flask==1.1.2
Flask-Caching==1.9.0
redis==3.5.3
Could you please provide more details about your environments so I can try to reproduce the issue?
I have created a minimal application containing the provided code which is supposed to produce the issue, however, tests are executing successfully.
===================================== test session starts ======================================
platform darwin -- Python 3.8.5, pytest-6.1.1, py-1.9.0, pluggy-0.13.1
plugins: flask-1.0.0
collected 1 item
test_get.py . [100%]
================================= 1 passed in 0.06s ===========================================
I'll be closing this for the time being, feel free to reopen it to provide a minimal, reproducible example.