Hi I'm writing an web application using axum, rusqlite and minijinja. I've been able to setup the axum::Router with a State that holds the Jinja templates and a database connection to SQLite. It works when try it on the browser. I also would like to test the endpoints. I've been able to use oneshot
to send a request and get a response in the tests.
However I've encountered a problem now that I want to write assertions against the database. IIUC constructing the axum::Router
consumes the connection so I can't use it after the axum::Router
has been constructed.
I'm unsure how to modify the code to be able to get the connection back after the application has processed the request. In the test context I'm using a in-memory database so I can't open a second connection to the database either. Any pointers to restructure the code?
Below are the relevant snippets of the application
// in lib.rs
#[derive(Clone)]
pub(crate) struct WebContext {
templates: Environment<'static>,
db: Arc<Mutex<Connection>>
}
pub fn new(db: Connection, template_dir: String) -> Router {
let source = path_loader(template_dir);
let mut env = Environment::new();
env.set_loader(source);
let db = Arc::new(Mutex::new(db));
let ctx = WebContext { templates: env, db };
Router::new()
.route("/", get(handler::index))
.route("/page/new", get(handler::new_page))
.route("/page/", post(handler::page_create))
.route("/upload/", post(handler::upload))
.with_state(ctx)
}
and the test code
fn setup_db() -> Connection {
let db = Connection::open_in_memory().expect("open db");
let mut file = File::open("sql/schema.sql").expect("open schema file");
let mut schema = String::new();
file.read_to_string(&mut schema)
.expect("reading schema file");
db.execute_batch(&schema).expect("Initialized the schema.");
db
}
fn setup_app(db: Connection) -> Router {
bliki::new(db, "./template/".to_string())
}
#[tokio::test]
async fn test_create_article() {
let db = setup_db();
let app = setup_app(db);
let mut params = HashMap::new();
params.insert("title", "Some title");
let body = serde_urlencoded::to_string(params).expect("encoding body");
let req = Request::builder()
.method("POST")
.uri("/page/")
.header("Content-Type", "application/x-www-form-urlencoded")
.body(body)
.unwrap();
let res = app.oneshot(req).await.unwrap();
assert_eq!(res.status(), StatusCode::OK);
// The assertion that results in the problem arising
let got_title: String = db.query_row_and_then("SELECT title FROM pages limit 1", [], |row| row.get(0)).expect("query title");
assert_eq!(got_title, "Some Title");
}
2 posts - 2 participants