#[tokio::test]
async fn ok() {
let db = connect().await?; // the error occurs here
let result = migrate_up(&db).await;
assert!(result.is_ok());
}
gives me the following very confusing error:
the ? operator can only be used in an async block that returns Result or Option (or another type that implements FromResidual)
the trait FromResidual<Result<Infallible, sea_orm::DbErr>> is not implemented for ()
Can someone please help with understanding how to get a value of the result without going viral with some crazy syntax?
Thanks @KSwanson , I got the point that the "?" has to return the actual error, not panic.
So there is a problem then. In my situation I would want to execute multiple different async functions which could return different types of errors. Eg:
let v1 = func1().await?;
let v2 = func2().await?;
So I am going to find a solution which does not require a Return<> type for the test ok() function. Is it possible? Can the "Result" panic instead?
So there's more or less 2 ways of dealing with this.
Option 1: Make your own Error Type
The way I usually do this is with an enum and derive_more:
use derive_more::{Debug, Display, Error, From}
enum MyError {
Db(DbErr),
// as an example of another type of error you might get
Io(std::io::Error),
}
async fn my_func() -> Result<(), MyError> {
// Or whatever your function does
Ok(())
}
Option 2: Panic
(I see this is the option you took)
In general it is better to return a Result<T,E> than to panic. But sometimes it doesn't really matter and you might as well just panic!. The most common case is when you are in a test, as tests rely on assert! and panic functionality; so why not panic anyway.
The simplest way to do this is to use the expect method:
let v1 = func1.await.expect("func1 failed");
(I see that you used unwrap, which is similar; but expect() takes a message to display in the panic output, which is often nice, and why I prefer it)
There are other options to handle results--you can use ok_or if there is a reasonable default value to use in case of an Err, for example.
Does ok().unwrap() throw a proper message, so I know what is going on when error (panic) occurs?
For example the DbError looks like this:
/// An error from unsuccessful database operations
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum DbErr {
/// There was a problem with the database connection
Conn(String),
/// An operation did not execute successfully
Exec(String),
/// An error occurred while performing a query
Query(String),
/// The record was not found in the database
RecordNotFound(String),
/// A custom error
Custom(String),
/// Error occurred while parsing value as target type
Type(String),
/// Error occurred while parsing json value as target type
Json(String),
/// A migration error
Migration(String),
}
Update: Looks like it does not.
I changed the db connection string so it is not correct, and I have got the following error:
thread 'tests::ok' panicked at 'called Option::unwrap() on a None value', data\src/lib.rs:37:53
Would be nice to include the actual error message from DbError.
No, but for a minor point I missed in your original post:
connect().await.ok().unwrap()
The ok() method turns it into an Option, which throws away the DbErr. So you get no information on the error.
Fortunately there's an easy solution: unwrap and expect both exist directly on Result, and in both cases they will print out the contents of the Error (assuming the Error implements Debug, which DbErr does in your case).
So you can change it to
connect().await.unwrap()
It can be nice to use expect, though, if you happen to have multiple calls to the same method, e.g.
Thank you so much. I simply used unwrap() and I have got exactly what I wanted
Now the error is the following (which is what I was looking for):
thread 'tests::ok' panicked at 'called Result::unwrap() on an Err value: Conn("error returned from database: (code: 14) unable to open database file")', data\src/lib.rs:37:48
This might be better (yet more verbosely) expressed with unwrap_or_else(|e| panic!("failed on input {}: {}", input, e)), since your code will allocate the error message eagerly, before even checking whether there was an error at all.