-
-
Notifications
You must be signed in to change notification settings - Fork 685
Description
Motivation
Currently, mocking only allows for explicitly defining list of events ahead of time. While this provides enough utility to get some basic testing accomplished, it limits the ability to assert the state of the database after a test has completed.
For example
struct SomeDbWrapper(DatabaseConnection);
impl SomeDbWrapper {
pub fn new(conn: DatabaseConnection) -> Self {
Self(conn)
}
pub async fn do_something_complicated(&self, other_data: Vec<(u32, u32, u32)>) -> Result<(), DbErr> {
let tx = self.0.begin().await?;
// This table has a composite key, that represents the only potential conflict
// if that is violated, we want to update the data column
let mut conflict_policy = OnConflict::new();
conflict_policy.update_columns(
Column::Data
);
// we want to clean up any data that isn't in the `other_data` provided so we will collect
// a filter here of the composite keys
let mut missing_items_filter = None;
for (ida, idb, data) in other_data {
if let Some(expr) = missing_items_filter {
missing_items_filter = Some(expr.or(
Column::IdA.eq(ida).and(
Column::IdB.eq(idb)
).not()
))
} else {
missing_items_filter = Some(
Column::IdA.eq(ida).and(
Column::IdB.eq(idb)
).not()
);
}
Insert(ActiveModel {
ida: Set(ida),
idb: Set(idb),
data: Set(data),
})
.on_conflict(on_conflict.clone())
.exec(&tx).await?;
}
let del = Entity::delete_many();
if let Some(expr) = missing_items_filter {
del = del.filter(expr);
}
del.exec(&tx).await?;
tx.commit().await?;
Ok(())
}
}The above would be very difficult to test with the current MockConnection since we cannot assert which operations have occurred, only what sql statements were executed. If we wanted to test that stale data is cleaned up after calling do_something_complicated we would need to attach to an actual database which can be a cumbersome process.
Proposed Solutions
While the work to build a fully functional in memory database from for testing is likely not something that is in the scope of this project, there is an escape hatch already provided and that is the MockDatabaseTrait,
by updating DatabaseConnectionType::MockDatabaseConnection(Arc<crate::MockDatabaseConnection>) to DatabaseConnectionType::MockDatabaseConnection(Arc<dyn MockDatabaseTrait>) (potentially with + Send + Sync + 'static in any combination) it would allow users to provide their own implementations w/o the maintenance burden.