I have a Flask application with a POST endpoint that I would like to test. The endpoint does some database munging, and in this particular case I'm trying to assert that calling the endpoint with a particular set of data doesn't change the database.
I have a pytest
fixture for my database model, an autouse=True
fixture that runs the test in a database transaction, and a fixture to generate a Flask test_client
:
@pytest.fixture()
def myfixture():
return MyModel.create(...)
@pytest.fixture
def testapp():
app.config['TESTING'] = True
with app.app_context():
yield app.test_client()
@pytest.fixture(autouse=True)
def with_database_txn():
with db.atomic() as txn:
yield
txn.rollback()
This works very well for most tests. However, when I'm testing calling my endpoints, I experience a strange issue with my database records:
def test_endpoint(myfixture, testapp):
assert MyModel.select().count() == 1
r = app.test_client().post('/endpoint', headers={...}, data=json.dumps({...}))
assert r.status_code == 200
assert r.data.decode() == 'no changes'
assert MyModel.select().count() == 1
My test fails on the final assert
, claiming that MyModel.select().count
has become 0
. The record still exists before the request returns, which I've verified in the handler for /endpoint
.
I am assuming (guessing, even) that there is some strange interaction going on between pytest
's fixtures, peewee
's transactions and flask
's request contexts that is causing the transaction to be rolled back before the second assertion is hit, but I can't find any information on what might be happening.
Viewing peewee
's log at DEBUG
level doesn't provide any information above the insertion of the fixtures and the selection of the records, though interestingly it also doesn't show anything to do with transactions at all, which I'm sure it used to... a smoking gun or simply a change in a recent version?
Either way, any help to track down what is going on would be most appreciated!
endpoint
code? How you initializeapp
in project and in tests? – Danila Ganchar