I'm trying to test a function that checks if a space exists in the database using sea-orm's MockDatabase. The function performs a COUNT query, but my test is failing.
pub async fn space_check_exist(db: &DatabaseConnection, space_id: &str) -> Result<bool, DbErr> {
let count = Space::find()
.filter(space::Column::SpaceId.eq(space_id))
.count(db)
.await?;
Ok(count > 0)
}
#[tokio::test]
async fn test_space_check_exist_when_space_exists() {
let db = MockDatabase::new(DatabaseBackend::Postgres)
.append_query_results([vec![space::Model {
id: 1,
space_id: "test-space-id".to_owned(),
space_status_id: 1,
space_config: Json::Null,
created_at: chrono::Utc::now().naive_utc(),
updated_at: chrono::Utc::now().naive_utc(),
deleted_at: None,
} as space::Model] as Vec<space::Model>])
.into_connection();
// Run test
let result = SpaceRepository::space_check_exist(&db, "test-space-id").await;
// Verify result
// assert!(result.is_ok());
assert!(result.unwrap());
}
thread 'modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists' panicked at src/modules/space/repository/space_repository.rs:41:9:
assertion failed: result.is_ok()
Compiling myapp v0.1.0 (/opt/app/myapp/app)
Finished `test` profile [unoptimized + debuginfo] target(s) in 11.08s
Running unittests src/lib.rs (target/debug/deps/myapp-23ce339f247c6933)
running 1 test
test modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists ... FAILED
successes:
successes:
failures:
---- modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists stdout ----
thread 'modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists' panicked at src/modules/space/repository/space_repository.rs:41:9:
assertion failed: result.is_ok()
stack backtrace:
0: rust_begin_unwind
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/std/src/panicking.rs:665:5
1: core::panicking::panic_fmt
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/panicking.rs:74:14
2: core::panicking::panic
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/panicking.rs:148:5
3: myapp::modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists::{{closure}}
at ./src/modules/space/repository/space_repository.rs:41:9
4: <core::pin::Pin<P> as core::future::future::Future>::poll
at /usr/local/rustup/toolchains/1.83.0-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:123:9
5: <core::pin::Pin<P> as core::future::future::Future>::poll
at /usr/local/rustup/toolchains/1.83.0-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:123:9
6: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:729:57
7: tokio::runtime::coop::with_budget
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/coop.rs:107:5
8: tokio::runtime::coop::budget
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/coop.rs:73:5
9: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:729:25
10: tokio::runtime::scheduler::current_thread::Context::enter
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:428:19
11: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:728:36
12: tokio::runtime::scheduler::current_thread::CoreGuard::enter::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:807:68
13: tokio::runtime::context::scoped::Scoped<T>::set
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/context/scoped.rs:40:9
14: tokio::runtime::context::set_scheduler::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/context.rs:180:26
15: std::thread::local::LocalKey<T>::try_with
at /usr/local/rustup/toolchains/1.83.0-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:283:12
16: std::thread::local::LocalKey<T>::with
at /usr/local/rustup/toolchains/1.83.0-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:260:9
17: tokio::runtime::context::set_scheduler
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/context.rs:180:9
18: tokio::runtime::scheduler::current_thread::CoreGuard::enter
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:807:27
19: tokio::runtime::scheduler::current_thread::CoreGuard::block_on
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:716:19
20: tokio::runtime::scheduler::current_thread::CurrentThread::block_on::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:196:28
21: tokio::runtime::context::runtime::enter_runtime
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/context/runtime.rs:65:16
22: tokio::runtime::scheduler::current_thread::CurrentThread::block_on
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:184:9
23: tokio::runtime::runtime::Runtime::block_on_inner
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/runtime.rs:368:47
24: tokio::runtime::runtime::Runtime::block_on
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/runtime.rs:342:13
25: myapp::modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists
at ./src/modules/space/repository/space_repository.rs:41:9
26: myapp::modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists::{{closure}}
at ./src/modules/space/repository/space_repository.rs:24:56
27: core::ops::function::FnOnce::call_once
at /usr/local/rustup/toolchains/1.83.0-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
28: core::ops::function::FnOnce::call_once
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
failures:
modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 87 filtered out; finished in 0.10s
error: test failed, to rerun pass `-p myapp --lib`
Compiling myapp v0.1.0 (/opt/app/myapp/app)
Finished `test` profile [unoptimized + debuginfo] target(s) in 9.65s
Running unittests src/lib.rs (target/debug/deps/myapp-23ce339f247c6933)
running 1 test
test modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists ... FAILED
successes:
successes:
failures:
---- modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists stdout ----
thread 'modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists' panicked at src/modules/space/repository/space_repository.rs:42:24:
called `Result::unwrap()` on an `Err` value: Type("A null value was encountered while decoding \"num_items\"")
stack backtrace:
0: rust_begin_unwind
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/std/src/panicking.rs:665:5
1: core::panicking::panic_fmt
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/panicking.rs:74:14
2: core::result::unwrap_failed
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/result.rs:1700:5
3: core::result::Result<T,E>::unwrap
at /usr/local/rustup/toolchains/1.83.0-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:1104:23
4: myapp::modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists::{{closure}}
at ./src/modules/space/repository/space_repository.rs:42:17
5: <core::pin::Pin<P> as core::future::future::Future>::poll
at /usr/local/rustup/toolchains/1.83.0-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:123:9
6: <core::pin::Pin<P> as core::future::future::Future>::poll
at /usr/local/rustup/toolchains/1.83.0-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/future.rs:123:9
7: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:729:57
8: tokio::runtime::coop::with_budget
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/coop.rs:107:5
9: tokio::runtime::coop::budget
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/coop.rs:73:5
10: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:729:25
11: tokio::runtime::scheduler::current_thread::Context::enter
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:428:19
12: tokio::runtime::scheduler::current_thread::CoreGuard::block_on::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:728:36
13: tokio::runtime::scheduler::current_thread::CoreGuard::enter::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:807:68
14: tokio::runtime::context::scoped::Scoped<T>::set
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/context/scoped.rs:40:9
15: tokio::runtime::context::set_scheduler::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/context.rs:180:26
16: std::thread::local::LocalKey<T>::try_with
at /usr/local/rustup/toolchains/1.83.0-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:283:12
17: std::thread::local::LocalKey<T>::with
at /usr/local/rustup/toolchains/1.83.0-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:260:9
18: tokio::runtime::context::set_scheduler
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/context.rs:180:9
19: tokio::runtime::scheduler::current_thread::CoreGuard::enter
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:807:27
20: tokio::runtime::scheduler::current_thread::CoreGuard::block_on
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:716:19
21: tokio::runtime::scheduler::current_thread::CurrentThread::block_on::{{closure}}
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:196:28
22: tokio::runtime::context::runtime::enter_runtime
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/context/runtime.rs:65:16
23: tokio::runtime::scheduler::current_thread::CurrentThread::block_on
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/scheduler/current_thread/mod.rs:184:9
24: tokio::runtime::runtime::Runtime::block_on_inner
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/runtime.rs:368:47
25: tokio::runtime::runtime::Runtime::block_on
at /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.42.0/src/runtime/runtime.rs:342:13
26: myapp::modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists
at ./src/modules/space/repository/space_repository.rs:42:9
27: myapp::modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists::{{closure}}
at ./src/modules/space/repository/space_repository.rs:24:56
28: core::ops::function::FnOnce::call_once
at /usr/local/rustup/toolchains/1.83.0-aarch64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
29: core::ops::function::FnOnce::call_once
at /rustc/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
failures:
modules::space::repository::space_repository::tests::test_space_check_exist_when_space_exists
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 87 filtered out; finished in 0.09s
error: test failed, to rerun pass `-p myapp --lib`
I've tried various approaches to mock the COUNT query result:
Using a full space::Model Using MockRow with different configurations
But I can't get it to work. How can I correctly mock a COUNT query result in sea-orm? Environment:
Rust 1.83.0 sea-orm 1.1.4
I could not solve the problem by the method described in the question.
Therefore, we used a different approach to solve the problem.
The following method solved the problem.
To mock the results of aggregate functions (COUNT) using Sea-ORM's MockDatabase
, you can use the append_query_results
method and BTreeMap
.
To mock the results of aggregate functions, follow these steps:
BTreeMap
with column names as keys and corresponding valuesBTreeMap
to the append_query_results
methodpub async fn space_check_exist(db: &DatabaseConnection, space_id: &str) -> Result<bool, DbErr> {
#[derive(Debug, FromQueryResult)]
struct CountResult {
space_count: i64,
}
let count = space::Entity::find()
.select_only()
.column_as(space::Column::Id.count(), "space_count")
.filter(space::Column::SpaceName.eq(space_name))
.into_model::<CountResult>()
.one(db)
.await?;
let space_name_count = count.map_or(0, |c| c.space_count);
Ok(space_name_count > 0)
}
#[tokio::test]
async fn test_space_check_exist_when_space_exists() {
let db = MockDatabase::new(DatabaseBackend::Postgres)
.append_query_results(vec![vec![BTreeMap::from([(
"space_count".to_string(),
Value::BigInt(Some(1)),
)])]])
.into_connection();
// test result
let result = SpaceRepository::space_check_exist(&db, "test_space")
.await
.unwrap();
assert!(result);
}
The key points are as follows:
column_as
in the query.Value::BigInt(Some(1))
.append_query_results
accepts data in the format of Vec<Vec<BTreeMap<...>>>
. The outer vector represents the number of query executions, and the inner vector represents the result rows for each query.To verify that queries are executed as expected, you can check the transaction log as follows:
// After test execution
let queries = db.into_transaction_log();
assert_eq!(queries.len(), 1);
// Verify the content of the executed SQL query
let executed_query = queries.first().unwrap();
assert_eq!(
executed_query,
&Transaction::from_sql_and_values(
DatabaseBackend::Postgres,
r#"SELECT COUNT("space"."id") AS "space_count" FROM "space" WHERE "space"."space_name" = $1 LIMIT $2"#,
vec!["test_space".into(), 1u64.into()]
)
);