I have a global crate exposing convenience functions to get data from a database using async functions (bb8_tiberius). This crate is used by multiple other crates (binaries) to provide an easy api in my code to access data, e.g.:
Now, in order to get good performance for database connetions I initialize a global connection pool and in every accessor function (e.g. get_user_by_id from above) get the pool out of a tokio::sync::OnceCell.
This works fine in all my applications - but creates a problem for tests, as it seems as #[tokio::test] creates a runtime for each individual test => I get " An error occured during the attempt of performing I/O: An error occured during the attempt of performing I/O: A Tokio 1.x context
was found, but it is being shutdown" errors whenever i try to run more then one test at a time.
My investigation leads me to beleive this is because the OnceCell is tied to one particualr runtime?
My question is twofold:
Is it possible to create a OnceCell (with lazy initialization) that works across multiple runtimes?
Alternatively - is it possible to get tokio to re-use the runtime across tests?
If the OnceCell is defined in your test, then you could put the OnceCell in a thread-local since tests use a single-threaded runtime meaning that there's a one-to-one mapping from thread to runtime. However, if it's defined in the library, then that might not work.
Other options would be:
Put a runtime in a (non-async) OnceCell and have each test use #[test] + a block_on on the shared runtime. (I.e. you're not using #[tokio::test])
Remove the global from your library and have it be an argument. Then create a separate value in each test.