Mock test case

This commit is contained in:
Chris Tsang 2021-06-13 23:38:21 +08:00
parent 6b7ea75393
commit faffc518ae
6 changed files with 85 additions and 40 deletions

View File

@ -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" ]

View File

@ -62,10 +62,7 @@ impl DatabaseConnection {
}
}
pub async fn execute(
&self,
stmt: Statement,
) -> Result<ExecResult, ExecErr> {
pub async fn execute(&self, stmt: Statement) -> Result<ExecResult, ExecErr> {
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<Option<QueryResult>, QueryErr> {
pub async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, 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<Vec<QueryResult>, QueryErr> {
pub async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, QueryErr> {
match self {
#[cfg(feature = "sqlx-mysql")]
DatabaseConnection::SqlxMySqlPoolConnection(conn) => conn.query_all(stmt).await,

View File

@ -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<Statement>,
exec_results: Vec<ExecResult>,
query_results: Vec<Vec<QueryResult>>,
exec_results: Vec<MockExecResult>,
query_results: Vec<Vec<MockRow>>,
}
#[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<MockExecResult>) -> Self {
self.exec_results.append(&mut vec);
self
}
pub fn append_query_results(mut self, mut vec: Vec<Vec<MockRow>>) -> Self {
self.query_results.append(&mut vec);
self
}
}
impl MockDatabaseTrait for MockDatabase {
fn execute(&mut self, counter: usize, statement: Statement) -> Result<ExecResult, ExecErr> {
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<Vec<QueryResult>, 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<BTreeMap<&str, Value>> for MockRow {
fn from(values: BTreeMap<&str, Value>) -> Self {
Self {
values: values.into_iter().map(|(k, v)| (k.to_owned(), v)).collect(),
}
}
}

View File

@ -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<DatabaseConnection, ConnectionErr> {
@ -47,30 +47,20 @@ impl MockDatabaseConnection {
impl MockDatabaseConnection {
pub async fn execute(&self, statement: Statement) -> Result<ExecResult, ExecErr> {
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<Option<QueryResult>, 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<Vec<QueryResult>, 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)
}
}

View File

@ -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;

View File

@ -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::<Value>::into(128), "name" => Into::<Value>::into("apple")
}
.into()]])
.into_database();
assert_eq!(
cake::Entity::find().into_json().one(&db).await.unwrap(),
Some(serde_json::json!({
"id": 128,
"name": "apple"
}))
);
}
}