@pytest.fixture(scope='session') def db(client): engine = Session.kw['bind'] conn = engine.connect() transaction = conn.begin() try: Base.metadata.create_all(bind=conn, checkfirst=False) yield conn finally: transaction.rollback() Session.configure(bind=engine) @pytest.fixture() def transaction(db): transaction = db.begin_nested() try: Session.configure(bind=db) yield transaction finally: transaction.rollback() @pytest.fixture() def session(transaction): return Session()And a test:
def test_create_full_data(transaction, session, client): response = client.post('/events/', json={ 'date': '2019-06-02', 'type': 'DONE', 'text': 'some stuff got done' }) transaction.rollback() actual = session.query(Event).one() compare(actual.date, expected=date(2019, 6, 2)) compare(type(actual), expected=Done) compare(response.json(), expected={ 'id': actual.id, 'date': '2019-06-02', 'type': 'DONE', 'text': 'some stuff got done' }) compare(response.status_code, expected=201)And some code:
@router.post("/", response_model=EventRead, status_code=201) def create_object( *, session: Session = Depends(db_session), event: EventCreate, ): """ Create new Event. """ with session.transaction: event = Event(**event.dict()) session.add(event) session.flush() session.expunge(event) return event
cheers,Chris
--SQLAlchemy -The Python SQL Toolkit and Object Relational MapperTo post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.---You received this message because you are subscribed to the Google Groups "sqlalchemy" group.To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.To post to this group, send email to sqlal...@googlegroups.com.Visit this group at https://groups.google.com/group/sqlalchemy.To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/430d4156-d9ff-4349-5be5-62bee6ea4627%40withers.org.For more options, visit https://groups.google.com/d/optout.
cheers,Chris--SQLAlchemy -The Python SQL Toolkit and Object Relational MapperTo post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.---You received this message because you are subscribed to the Google Groups "sqlalchemy" group.To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.To post to this group, send email to sqlal...@googlegroups.com.Visit this group at https://groups.google.com/group/sqlalchemy.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/471aa85f-776f-b899-1fe8-2f3cc009da38%40withers.org.
On Tue, Jun 4, 2019, at 4:33 PM, Chris Withers wrote:
So, how do I roll back the further subtransaction created by the web
framework instantiating Session from a sessionmaker bound to the
connection in which begin_nested() has been called, which under non-test
running would actually be a top level transaction assuming I understand
the pattern correctly, in such as way that if the code-under-test has
committed on is session, the session being used to check expectations in
the unit test will see the results, but if it that commit has been
forgotten, it will not?
I'm not following all your code but if there are two sessions in play I'd probably try to avoid that, there should be only one Session you care about. the test fixtures should be external to everything and make sure there's just the one session. if there are two in play, I'm not sure how they both get bound to your test transaction.
import os from diary.model import Session, Base, Event, Types from sqlalchemy import create_engine engine = create_engine(os.environ['TEST_DB_URL']) Session.configure(bind=engine) conn = engine.connect() transaction = conn.begin() try: Base.metadata.create_all(bind=conn, checkfirst=False) Session.configure(bind=conn) sub_transaction = conn.begin_nested() try: session = Session() # code under test: event = Event(date='2019-06-02', type=Types.done, text='some stuff got done') session.add(event) session.flush() session.close() # test: session.rollback() assert session.query(Event).count() == 0 finally: sub_transaction.rollback() finally: transaction.rollback()
On 04/06/2019 23:21, Mike Bayer wrote:>>> I'm not following all your code but if there are two sessions in play> I'd probably try to avoid that, there should be only one Session you> care about.This comes back to something I asked you about on Twitter a while ago:the code under test gets its session by calling a sessionmaker; how canI have that return an existing session, which appears to be what you'resuggesting, rather than a new suggestion, which appears to be all theycan do.
> the test fixtures should be external to everythingI don't understand what you mean by this.
> and make> sure there's just the one session. if there are two in play, I'm not> sure how they both get bound to your test transaction.I believe they start a nested transaction?
Chris--SQLAlchemy -The Python SQL Toolkit and Object Relational MapperTo post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.---You received this message because you are subscribed to the Google Groups "sqlalchemy" group.To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.To post to this group, send email to sqlal...@googlegroups.com.Visit this group at https://groups.google.com/group/sqlalchemy.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/50bb9529-f98b-24aa-484f-1274c8fe3290%40withers.org.
Chris
--SQLAlchemy -The Python SQL Toolkit and Object Relational MapperTo post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.---You received this message because you are subscribed to the Google Groups "sqlalchemy" group.To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.To post to this group, send email to sqlal...@googlegroups.com.Visit this group at https://groups.google.com/group/sqlalchemy.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/55721019-2de3-12b4-3796-90ca34b5ea4c%40withers.org.
That session.close() appears to be the problem. It's a normal and required part of the code under test, but it throws away the SessionTransaction without rolling it back, so by the time the test does session.rollback(), it's doing it on a new SessionTransaction and so has no effect and the assertion fails because there event created is still around...
Is this a bug or am I just confusing myself and everyone else?
I can run your script if you remove the "diary" thing from it
import os from sqlalchemy import Column, Integer, Text from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker Base = declarative_base() Session = sessionmaker() class Event(Base): __tablename__ = 'entry' id = Column(Integer(), primary_key=True) text = Column(Text) engine = create_engine(os.environ['TEST_DB_URL']) Session.configure(bind=engine) conn = engine.connect() transaction = conn.begin()
try: Base.metadata.create_all(bind=conn, checkfirst=False) Session.configure(bind=conn) sub_transaction = conn.begin_nested() try: session = Session() # code under test:
event = Event(text='some stuff got done') session.add(event) session.flush() session.close()
# test: session.rollback() assert session.query(Event).count() == 0 finally: sub_transaction.rollback() finally: transaction.rollback()
Chris--SQLAlchemy -The Python SQL Toolkit and Object Relational MapperTo post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.---You received this message because you are subscribed to the Google Groups "sqlalchemy" group.To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.To post to this group, send email to sqlal...@googlegroups.com.Visit this group at https://groups.google.com/group/sqlalchemy.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/806b6413-8537-8813-5c32-1238086300dd%40withers.org.
> the test harness is giving you two choices. you can look at the state> of the DB after your program has done some things and *before* your> harness has reversed its work, or you can look at the state of the DB> *after* your harness has reversed its work.Unless I'm missing something, neither of these let the test confirm thatthe code under test has called commit() when it should.cheers,Chris
--SQLAlchemy -The Python SQL Toolkit and Object Relational MapperTo post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.---You received this message because you are subscribed to the Google Groups "sqlalchemy" group.To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.To post to this group, send email to sqlal...@googlegroups.com.Visit this group at https://groups.google.com/group/sqlalchemy.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/d7f7c9ac-2d32-6e60-efac-f86b501683f7%40withers.org.
cheers,Chris--SQLAlchemy -The Python SQL Toolkit and Object Relational MapperTo post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.---You received this message because you are subscribed to the Google Groups "sqlalchemy" group.To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.To post to this group, send email to sqlal...@googlegroups.com.Visit this group at https://groups.google.com/group/sqlalchemy.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/c5c0a17c-0671-b86c-842e-f03cded132ba%40withers.org.