diff --git a/Cargo.toml b/Cargo.toml index dda0f88c..0cc21a12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,9 +34,13 @@ sqlx = { version = "^0.5", optional = true } strum = { version = "^0.20", features = [ "derive" ] } serde_json = { version = "^1", optional = true } +[dev-dependencies] +async-std = { version = "^1.9", features = [ "attributes" ] } +maplit = { version = "^1" } + [features] debug-print = [] -default = [ "macros", "with-json", "mock", "sqlx-mysql", "runtime-async-std-native-tls" ] +default = [ "macros", "with-json", "mock" ] macros = [ "sea-orm-macros" ] mock = [] with-json = [ "serde_json", "sea-query/with-json" ] diff --git a/src/database/connection.rs b/src/database/connection.rs index 85ed546c..4440ad84 100644 --- a/src/database/connection.rs +++ b/src/database/connection.rs @@ -62,10 +62,7 @@ impl DatabaseConnection { } } - pub async fn execute( - &self, - stmt: Statement, - ) -> Result { + pub async fn execute(&self, stmt: Statement) -> Result { match self { #[cfg(feature = "sqlx-mysql")] DatabaseConnection::SqlxMySqlPoolConnection(conn) => conn.execute(stmt).await, @@ -75,10 +72,7 @@ impl DatabaseConnection { } } - pub async fn query_one( - &self, - stmt: Statement, - ) -> Result, QueryErr> { + pub async fn query_one(&self, stmt: Statement) -> Result, QueryErr> { match self { #[cfg(feature = "sqlx-mysql")] DatabaseConnection::SqlxMySqlPoolConnection(conn) => conn.query_one(stmt).await, @@ -88,10 +82,7 @@ impl DatabaseConnection { } } - pub async fn query_all( - &self, - stmt: Statement, - ) -> Result, QueryErr> { + pub async fn query_all(&self, stmt: Statement) -> Result, QueryErr> { match self { #[cfg(feature = "sqlx-mysql")] DatabaseConnection::SqlxMySqlPoolConnection(conn) => conn.query_all(stmt).await, diff --git a/src/database/mock.rs b/src/database/mock.rs index 8336d093..a6c3b456 100644 --- a/src/database/mock.rs +++ b/src/database/mock.rs @@ -1,15 +1,18 @@ -use crate::{ExecErr, ExecResult, MockDatabaseTrait, QueryErr, QueryResult, Statement, TypeErr}; +use crate::{ + Database, DatabaseConnection, ExecErr, ExecResult, ExecResultHolder, MockDatabaseConnection, + MockDatabaseTrait, QueryErr, QueryResult, QueryResultRow, Statement, TypeErr, +}; use sea_query::{Value, ValueType}; use std::collections::BTreeMap; #[derive(Debug, Default)] pub struct MockDatabase { transaction_log: Vec, - exec_results: Vec, - query_results: Vec>, + exec_results: Vec, + query_results: Vec>, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct MockExecResult { pub last_insert_id: u64, pub rows_affected: u64, @@ -24,14 +27,33 @@ impl MockDatabase { pub fn new() -> Self { Default::default() } + + pub fn into_database(self) -> Database { + Database { + connection: DatabaseConnection::MockDatabaseConnection(MockDatabaseConnection::new( + self, + )), + } + } + + pub fn append_exec_results(mut self, mut vec: Vec) -> Self { + self.exec_results.append(&mut vec); + self + } + + pub fn append_query_results(mut self, mut vec: Vec>) -> Self { + self.query_results.append(&mut vec); + self + } } impl MockDatabaseTrait for MockDatabase { fn execute(&mut self, counter: usize, statement: Statement) -> Result { self.transaction_log.push(statement); if counter < self.exec_results.len() { - Err(ExecErr) - // Ok(self.exec_results[counter].clone()) + Ok(ExecResult { + result: ExecResultHolder::Mock(std::mem::take(&mut self.exec_results[counter])), + }) } else { Err(ExecErr) } @@ -44,8 +66,12 @@ impl MockDatabaseTrait for MockDatabase { ) -> Result, QueryErr> { self.transaction_log.push(statement); if counter < self.query_results.len() { - Err(QueryErr) - // Ok(self.query_results[counter].clone()) + Ok(std::mem::take(&mut self.query_results[counter]) + .into_iter() + .map(|row| QueryResult { + row: QueryResultRow::Mock(row), + }) + .collect()) } else { Err(QueryErr) } @@ -64,3 +90,11 @@ impl MockRow { self.values.into_iter() } } + +impl From> for MockRow { + fn from(values: BTreeMap<&str, Value>) -> Self { + Self { + values: values.into_iter().map(|(k, v)| (k.to_owned(), v)).collect(), + } + } +} diff --git a/src/driver/mock.rs b/src/driver/mock.rs index 9189e306..7352bc44 100644 --- a/src/driver/mock.rs +++ b/src/driver/mock.rs @@ -21,8 +21,8 @@ pub trait MockDatabaseTrait: Send { } impl MockDatabaseConnector { - pub fn accepts(_string: &str) -> bool { - true + pub fn accepts(string: &str) -> bool { + string.starts_with("mock://") } pub async fn connect(_string: &str) -> Result { @@ -47,30 +47,20 @@ impl MockDatabaseConnection { impl MockDatabaseConnection { pub async fn execute(&self, statement: Statement) -> Result { debug_print!("{}", statement); - self.counter.fetch_add(1, Ordering::SeqCst); - self.mocker - .lock() - .unwrap() - .execute(self.counter.load(Ordering::SeqCst), statement) + let counter = self.counter.fetch_add(1, Ordering::SeqCst); + self.mocker.lock().unwrap().execute(counter, statement) } pub async fn query_one(&self, statement: Statement) -> Result, QueryErr> { debug_print!("{}", statement); - self.counter.fetch_add(1, Ordering::SeqCst); - let result = self - .mocker - .lock() - .unwrap() - .query(self.counter.load(Ordering::SeqCst), statement)?; + let counter = self.counter.fetch_add(1, Ordering::SeqCst); + let result = self.mocker.lock().unwrap().query(counter, statement)?; Ok(result.into_iter().next()) } pub async fn query_all(&self, statement: Statement) -> Result, QueryErr> { debug_print!("{}", statement); - self.counter.fetch_add(1, Ordering::SeqCst); - self.mocker - .lock() - .unwrap() - .query(self.counter.load(Ordering::SeqCst), statement) + let counter = self.counter.fetch_add(1, Ordering::SeqCst); + self.mocker.lock().unwrap().query(counter, statement) } } diff --git a/src/driver/sqlx_mysql.rs b/src/driver/sqlx_mysql.rs index a53e6142..6d44d06e 100644 --- a/src/driver/sqlx_mysql.rs +++ b/src/driver/sqlx_mysql.rs @@ -6,7 +6,7 @@ use sqlx::{ sea_query::sea_query_driver_mysql!(); use sea_query_driver_mysql::bind_query; -use crate::{debug_print, executor::*, DatabaseConnection, Statement, ConnectionErr}; +use crate::{debug_print, executor::*, ConnectionErr, DatabaseConnection, Statement}; pub struct SqlxMySqlConnector; diff --git a/src/query/json.rs b/src/query/json.rs index 4cc07157..0487dc69 100644 --- a/src/query/json.rs +++ b/src/query/json.rs @@ -59,3 +59,29 @@ impl FromQueryResult for JsonValue { } } } + +#[cfg(test)] +#[cfg(feature = "mock")] +mod tests { + use crate::tests_cfg::cake; + use crate::{entity::*, MockDatabase}; + use sea_query::Value; + + #[async_std::test] + async fn to_json_1() { + let db = MockDatabase::new() + .append_query_results(vec![vec![maplit::btreemap! { + "id" => Into::::into(128), "name" => Into::::into("apple") + } + .into()]]) + .into_database(); + + assert_eq!( + cake::Entity::find().into_json().one(&db).await.unwrap(), + Some(serde_json::json!({ + "id": 128, + "name": "apple" + })) + ); + } +}