use async_trait::async_trait;
#[async_trait]
pub trait UnitOfWork: Send {
type Error;
async fn commit(self: Box<Self>) -> Result<(), Self::Error>;
async fn rollback(self: Box<Self>) -> Result<(), Self::Error>;
}
#[cfg(test)]
mod tests {
use std::sync::{
Arc,
atomic::{AtomicU8, Ordering},
};
use super::*;
struct SpyTx(Arc<AtomicU8>);
#[async_trait]
impl UnitOfWork for SpyTx {
type Error = std::convert::Infallible;
async fn commit(self: Box<Self>) -> Result<(), Self::Error> {
self.0.store(1, Ordering::SeqCst);
Ok(())
}
async fn rollback(self: Box<Self>) -> Result<(), Self::Error> {
self.0.store(2, Ordering::SeqCst);
Ok(())
}
}
#[tokio::test]
async fn commit_consumes_and_runs() {
let state = Arc::new(AtomicU8::new(0));
let uow: Box<dyn UnitOfWork<Error = std::convert::Infallible>> = Box::new(SpyTx(state.clone()));
uow.commit().await.unwrap();
assert_eq!(state.load(Ordering::SeqCst), 1);
}
#[tokio::test]
async fn rollback_consumes_and_runs() {
let state = Arc::new(AtomicU8::new(0));
let uow: Box<dyn UnitOfWork<Error = std::convert::Infallible>> = Box::new(SpyTx(state.clone()));
uow.rollback().await.unwrap();
assert_eq!(state.load(Ordering::SeqCst), 2);
}
}