In this example there is a test to check that a table made with SeaORM syntax is correct. I want to use a test like that in a code base very similar to the one from the SeaORM tutorial.
./Cargo.toml
[package]
name = "media_wiki"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
futures = "0.3.21"
sea-orm = { version = "^0.9.0", features = [ "sqlx-sqlite", "runtime-async-std-native-tls", "macros" ] }
sea-orm-migration = "^0.9.0"
./src/main.rs
mod migrator;
use futures::executor::block_on;
use sea_orm::{ConnectionTrait, Database, DbBackend, DbErr, Statement};
use sea_orm_migration::prelude::*;
const DATABASE_URL: &str = "sqlite:./sqlite.db?mode=rwc";
async fn run() -> Result<(), DbErr> {
let db = Database::connect(DATABASE_URL).await?;
let db_name = "media_wiki_db";
let db = &match db.get_database_backend() {
DbBackend::MySql => {
db.execute(Statement::from_string(
db.get_database_backend(),
format!("CREATE DATABASE IF NOT EXISTS `{}`;", db_name),
))
.await?;
let url = format!("{}/{}", DATABASE_URL, db_name);
Database::connect(&url).await?
}
DbBackend::Postgres => {
db.execute(Statement::from_string(
db.get_database_backend(),
format!("DROP DATABASE IF EXISTS \"{}\";", db_name),
))
.await?;
db.execute(Statement::from_string(
db.get_database_backend(),
format!("CREATE DATABASE \"{}\";", db_name),
))
.await?;
let url = format!("{}/{}", DATABASE_URL, db_name);
Database::connect(&url).await?
}
DbBackend::Sqlite => db,
};
let schema_manager = SchemaManager::new(db); // To investigate the schema
migrator::Migrator::refresh(db).await?;
assert!(schema_manager.has_table("File").await?);
assert!(schema_manager.has_table("FileName").await?);
Ok(())
}
fn main() {
if let Err(err) = block_on(run()) {
panic!("{}", err);
}
}
./src/migrator/mod.rs
use sea_orm_migration::prelude::*;
mod m20220726_000001_create_schema;
pub struct Migrator;
#[async_trait::async_trait]
impl MigratorTrait for Migrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
vec![
Box::new(m20220726_000001_create_schema::Migration),
]
}
}
./src/migrator/m20220726_000001_create_schema.rs
use sea_orm_migration::prelude::*;
pub struct Migration;
impl MigrationName for Migration {
fn name(&self) -> &str {
"m_20220726_000001_create_schema"
}
}
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(file_table())
.create_table(file_name_table())
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(File::Table).to_owned())
.drop_table(Table::drop().table(FileName::Table).to_owned())
.await
}
}
#[derive(Iden)]
pub enum File {
Table,
Id,
Rating,
}
#[derive(Iden)]
pub enum FileName {
Table,
Id,
Name,
Lang,
FileId,
}
fn file_table() -> TableCreateStatement {
Table::create()
.table(File::Table)
.if_not_exists()
.col(
ColumnDef::new(File::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(File::Rating).double())
.to_owned()
}
fn file_name_table() -> TableCreateStatement {
Table::create()
.table(FileName::Table)
.if_not_exists()
.col(
ColumnDef::new(FileName::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(
ColumnDef::new(FileName::Name)
.text()
.not_null(),
)
.col(ColumnDef::new(FileName::Lang)
.text()
.not_null(),
)
.col(
ColumnDef::new(FileName::FileId)
.integer()
.not_null(),
)
.foreign_key(
ForeignKey::create()
.name("fk_file-name_file")
.from(FileName::Table, FileName::FileId)
.to(File::Table, File::Id)
.on_delete(ForeignKeyAction::Cascade)
.on_update(ForeignKeyAction::Cascade)
)
.to_owned()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_file_table() {
assert_eq!(
file_table().to_string(SqliteQueryBuilder),
vec![
r#"CREATE TABLE IF NOT EXISTS "File" ("#,
r#""Id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,"#,
r#""Rating" double,"#,
r#")"#,
].join(" ")
);
}
#[test]
fn test_create_file_name_table() {
assert_eq!(
file_name_table().to_string(SqliteQueryBuilder),
vec![
r#"CREATE TABLE IF NOT EXISTS "FileName" ("#,
r#""Id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,"#,
r#""Name" text NOT NULL,"#,
r#""Lang" text NOT NULL,"#,
r#""FileId" integer NOT NULL,"#,
r#")"#,
].join(" ")
);
}
}
When I run cargo test
I get the following error:
❯ cargo test
Compiling media_wiki v0.1.0 (/home/user/code/rust/media_wiki)
error[E0599]: no method named `create_table` found for opaque type `impl futures::Future<Output = Result<(), sea_orm_migration::DbErr>>` in the current scope
--> src/migrator/m20220726_000001_create_schema.rs:16:14
|
16 | .create_table(file_name_table())
| ^^^^^^^^^^^^ method not found in `impl futures::Future<Output = Result<(), sea_orm_migration::DbErr>>`
error[E0599]: no method named `drop_table` found for opaque type `impl futures::Future<Output = Result<(), sea_orm_migration::DbErr>>` in the current scope
--> src/migrator/m20220726_000001_create_schema.rs:22:14
|
22 | .drop_table(Table::drop().table(FileName::Table).to_owned())
| ^^^^^^^^^^ method not found in `impl futures::Future<Output = Result<(), sea_orm_migration::DbErr>>`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `media_wiki` due to 2 previous errors