should `DatabaseConnectionType::MockDatabaseConnection` use `Arc<dyn MockDatabaseTrait>`
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 9.9k
- Forks
- 734
- Avg merge
- 6h 36m
- Merged PRs (30d)
- 8
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.
Additional Information
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating DatabaseConnectionType::MockDatabaseConnection and the MockDatabaseTrait definition, then inspect their uses and the existing mock connection tests. Determine the required trait bounds and compatibility impact; done means users can provide custom MockDatabaseTrait implementations while existing mock behavior continues to work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- databases
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100