Running locally, Python 3.12, Streamlit 1.40.1
Hi, please forgive the big setup here, trying to map my problem exactly. I am writing a bunch of tests for my streamlit app, and so far it has worked well using standard pytest and mocking out my Postgres queries with monkeypatch. However, I’m now trying to recover data from an INSERT ... RETURNING ...; query and having a lot of trouble getting the scoping on my mock correct.
Imagine I have an app setup as follows:
.
├── poetry.lock
├── pyproject.toml
└── streamlit
├── app.py
├── classes
│ ├── __init__.py
│ └── burg.py
└── tests
├── __init__.py
└── test_app.py
Where my main app is in app.py, and I have a class doing the lifting in classes/burg.py.
burg.py
import streamlit as st
from sqlalchemy.sql import text
class Burg:
pass
class Burger(Burg):
@staticmethod
def flip_burger() -> list[str]:
with st.session_state.conn.session as session:
new_antigens = session.execute(
text(
"INSERT INTO user_logs (update_time, antigens_id, users_id, "
"site_page, status_changed) VALUES ('2024-10-10 00:00:00', 1, 1, "
"'burgers', 'flipped') returning user_logs_id;"
)
)
session.commit()
new_ids = [str(new_id[0]) for new_id in new_antigens]
return new_ids
app.py
import streamlit as st
from classes.burg import Burger
st.session_state.conn = st.connection("postgres") # init psql connection
Burger.flip_burger()
test_app.py
import streamlit as st
import pandas as pd
from classes.burg import Burger
class Test_Burger:
def test_flip_burger(self, monkeypatch):
class session_state:
class conn:
class session:
def __enter__(self):
return self
def __exit__(self):
pass
@staticmethod
def execute(null):
return pd.DataFrame({"ids": [100]})
def mock_conn(*args, **kwargs):
return session_state()
monkeypatch.setattr(st, "session_state", mock_conn)
borger = Burger()
assert borger.flip_burger() == [100]
The gist is I am inserting into my logs table and this function returns the ids of the rows that have been inserted.
I would like to use the monkeypatched method above to mock st.session_state.conn.session and .execute() so I can returned a couple fake ids and test my function.
I’ve tried a few different iterations of the session_state mock class (from How to monkeypatch/mock modules and environments - pytest documentation), but the closest I can get is:
FAILED tests/test_app.py::Test_Burger::test_flip_burger - AttributeError: 'function' object has no attribute 'conn'
I have a feeling I’m just not scoping or designing my session_state replacement correctly. What would be the right way to mock this out with monkeypatch?