I know Dependency Injection and OO is not super popular with Rust but coming from Go I want to be able to mock and test a web server across the "typical" 3 layers stack (controller, service, repository).
I managed to achieve dependency injection so:
#[automock]
pub trait Repository {
fn save_into_db(item: Item) -> Result<(), Error>
}
#[derive(Clone)]
pub struct Service {
repository: Arc<dyn Repository>
}
impl Service {
fn new(repository: Arc<dyn Repository>) -> Self {
Self {
repository
}
}
}
However when I try to inject the dynamoDB Client as provided by AWS SDK Rust (https://docs.aws.amazon.com/sdk-for-rust/latest/dg/rust_dynamodb_code_examples.html) and construct the Repository, I can't pass the Client object that implement the sdk methods as a trait to the repository constructor as I would normally do in Go.
#[automock]
pub trait IDynamo: Send + Sync {
fn put_item(&self) -> PutItem;
fn query(&self) -> Query;
}
#[derive(Clone)]
pub struct Repository {
pub dynamo: Arc<dyn IDynamo>,
}
impl Repository {
pub fn new(dynamo: Arc<dyn IDynamo>) -> Self {
Self {
dynamo
}
}
}
...
async fn main() -> std::io::Result<()> {
...
let repository = Repository::new(client) <- this errors
...
mismatched types expected struct
Arc<(dyn IDynamo + 'static)>
found structaws_sdk_dynamodb::Client
The error is clear but this would normally succeed in Go because the struct implements the interface.
What is the Rusty way to achieve the same behaviour? I am also open to hear other non OO ways that may be more suited for Rust as long as they can achieve the same test coverage.
Thanks