Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#[sqlx::test] #330

Closed
abonander opened this issue May 21, 2020 · 5 comments · Fixed by #2001
Closed

#[sqlx::test] #330

abonander opened this issue May 21, 2020 · 5 comments · Fixed by #2001
Labels

Comments

@abonander
Copy link
Collaborator

abonander commented May 21, 2020

Thought of this one a while ago before public release but it didn't make it to this issue tracker.

Basically enables this pattern:

#[sqlx::test]
async fn test_use_database(conn: PgConnection) -> anyhow::Result<()> {
    // ... test code here
}

Where the emitted code is equivalent to something like this:

#[tokio::test] // or `#[async_std::test]` depending on which runtime feature is activated
async fn test_use_database() -> anyhow::Result<()> {
    use sqlx::Connect;

    // ideally this should be a more useful error as `VarError` does not report the variable in question, making the message useless
    let database_url = dotenv::var("DATABASE_URL")?;

    // implementation note: for the identifier make sure to reuse the exact token that was given for the arg name in the input so this obeys hygiene and can be referenced by the test code
    let conn: PgConnection = sqlx::Connect::connect(database_url).await?;
   
    // ... test code here
}

@mehcode has a version of this on develop already, although it only covers the #[tokio::test]/#[async_std::test] part (which effectively just inlines what those attributes do): https://github.com/launchbadge/sqlx/blob/develop/sqlx-rt-macros/src/lib.rs

The only real question I think is what to do as far as the error from dotenv::var() because the error that's emitted is not helpful at all in the case of DATABASE_URL not being defined, and would be compounded by the fact that the user wouldn't be able to immediately see the code where it came from.

My current best idea is to add a (hidden?) variant to sqlx::Error, since the function result's error type would need to be convertible from sqlx::Error anyway for the connect() call and any calls that actually use the connection. Some users will probably elect to just use sqlx::Result anyway.

@abonander abonander added E-medium enhancement New feature or request proposal labels May 21, 2020
@mehcode
Copy link
Member

mehcode commented May 21, 2020

We should put the connection into a never-committed transaction. The general idea is anything done to the test transaction is not visible outside that test.

See http://docs.diesel.rs/diesel/connection/trait.Connection.html#method.begin_test_transaction for a similar concept in Diesel.


Additionally, we should probably add a way to create a singleton Pool ( singleton meaning the pool has a single connection it manages and doesn't ever add any more ) from a connection like PgPool::singleton(conn) ( bikeshedding on the name there welcome ) so someone can utilize sqlx::test with a test structure that wants a pool.

@abonander
Copy link
Collaborator Author

I agree with the transaction but the attribute should accept an argument to disable this for stuff that doesn't work in a transaction (I'm not sure what).

#[sqlx::test(in_tx = false)] (Bikeshedding?)

@jimmycuadra
Copy link

jimmycuadra commented Sep 13, 2020

We should put the connection into a never-committed transaction. The general idea is anything done to the test transaction is not visible outside that test.

See http://docs.diesel.rs/diesel/connection/trait.Connection.html#method.begin_test_transaction for a similar concept in Diesel.

Was this ever implemented? I'm looking for a way to do this with sqlx (I used to do it in Diesel with the linked method) but I don't see anything in sqlx-test's source code that would do this.

Edit: BTW, it would be helpful to have documentation for sqlx::pool::PoolOptions::{after_connect, before_acquire, after_release} and examples of usage. In Diesel I used a similar "on acquire" hook to achieve test transactions, so I thought this might be the way to do it in sqlx, but wasn't able to figure it out. I was also puzzled by the Fut generic parameter to before_acquire, which doesn't seem to be used anywhere in the signature. My attempts to use the function kept failing with type inference errors because the type of Fut couldn't be determined.

@rex-remind101
Copy link

any chance this will get implemented, and furthermore is there an interface that simplifies fakes or mocks of PgConnection when one doesn't need to actually call all the way to the database?

thanks

@abonander
Copy link
Collaborator Author

I've spent the last week or so prototyping this attribute after having finally nailed down exactly how we want it to work: #2001

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants