# zero

## [rust] DB integration tests with Rocket + Diesel

Using Diesel with Rocket usually require the use of rocket_sync_db_pools crate which hides the complicated setup of initializing a DB connection pool and expose it to handlers via a opaque type that you can call run on to get a Future back and only in that Future you will get a connection.

This makes writing a integration test with a Rocket handler a bit more complicated because the impl of the DB Pool guard type is generated on-the-fly and not bind to a trait, so we can't just write a mock implementation of it.

After some trial and error, I realized that you can initialize Rocket to the Ignite state (initialized but not launched/listening yet). We generate a new test DB on-the-fly for every test so we also need to config the Rocket instance to use the right test-specific DB url. Here's the code doing so:

pub async fn rocket_test<F, Fut, R>(&self, f: F) -> anyhow::Result<R>
where
F: FnOnce(DbConnection) -> Fut,
Fut: Future<Output = R> + Send + 'static,
R: Send + 'static,
{
let figment = rocket::Config::figment()
.merge(("databases.db.url", self.db_url.clone()));
let rocket = rocket::custom(figment)
.attach(DbConnection::fairing())
.ignite()
.await?;
let conn = DbConnection::get_one(&rocket)
.await
.ok_or(MyError::DbError(
"unable to get db connection".to_string(),
))?;

let result = f(conn).await;

rocket.shutdown().notify();

Ok(result)
}


and therefore, you can write tests as such:

rocket_test(async move |conn| {
let ret = a_rocket_handler(
conn,
params,
)
.await
.expect_err("handler should fail");

assert_eq!(
ret,