{% import "application/macros.tera" as macros %}{% set required = fields | filter(attribute="required_string", value=true) %}{% set string_vos = fields | filter(attribute="string_vo", value=true) %}use std::sync::Arc;
use async_trait::async_trait;
use crate::domain::{{ snake }}::{
errors::{{ pascal }}Error,
model::{{ pascal }},
repository::{{ pascal }}RepositoryTrait,
use_cases::get_{{ snake }}::{Get{{ pascal }}Params, Get{{ pascal }}UseCaseTrait},
};
pub struct Get{{ pascal }}UseCaseImpl {
pub repository: Arc<dyn {{ pascal }}RepositoryTrait>,
}
#[async_trait]
impl Get{{ pascal }}UseCaseTrait for Get{{ pascal }}UseCaseImpl {
async fn execute(&self, params: Get{{ pascal }}Params) -> Result<{{ pascal }}, {{ pascal }}Error> {
tracing::info!(id = %params.id, "get_{{ snake }}: start");
let result = self.repository.find_by_id(params.id).await.inspect_err(|e| tracing::error!(error = %e, "get_{{ snake }}: repository failed"))?;
result.ok_or_else(|| {
let err = {{ pascal }}Error::NotFound;
tracing::warn!(error = %err, "get_{{ snake }}: rejected");
err
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::domain::{{ snake }}::{
model::{{ "{" }}{{ pascal }}, {{ pascal }}Id, {{ pascal }}Props},
repository::mocks::Mock{{ pascal }}Repository,
};
use crate::domain::shared::repository_error::RepositoryError;
{% for import in test_imports %} use {{ import }};
{% endfor %}
#[tokio::test]
async fn should_return_{{ snake }}_when_id_exists() {
let entity = {{ pascal }}::new({{ pascal }}Props {
{{ macros::props(fields=fields, word="example") }} }).unwrap();
let entity_id = entity.id;
let mut mock_repo = Mock{{ pascal }}Repository::new();
mock_repo
.expect_find_by_id()
.returning(move |_| Ok(Some(entity.clone())));
let use_case = Get{{ pascal }}UseCaseImpl {
repository: Arc::new(mock_repo),
};
let result = use_case.execute(Get{{ pascal }}Params { id: entity_id }).await;
assert!(result.is_ok());{% if required %}
assert_eq!(result.unwrap().{{ required.0.name }}, "example");{% elif string_vos %}
assert_eq!(result.unwrap().{{ string_vos.0.name }}.value(), "example");{% endif %}
}
#[tokio::test]
async fn should_return_not_found_when_id_does_not_exist() {
let mut mock_repo = Mock{{ pascal }}Repository::new();
mock_repo.expect_find_by_id().returning(|_| Ok(None));
let use_case = Get{{ pascal }}UseCaseImpl {
repository: Arc::new(mock_repo),
};
let result = use_case
.execute(Get{{ pascal }}Params { id: {{ pascal }}Id::generate() })
.await;
assert!(result.is_err());
assert_eq!(result.unwrap_err().to_string(), "{{ snake }}.not_found");
}
#[tokio::test]
async fn should_return_repository_error_when_the_store_is_unavailable() {
let mut mock_repo = Mock{{ pascal }}Repository::new();
mock_repo
.expect_find_by_id()
.returning(|_| Err(RepositoryError::Unavailable));
let use_case = Get{{ pascal }}UseCaseImpl {
repository: Arc::new(mock_repo),
};
let result = use_case
.execute(Get{{ pascal }}Params { id: {{ pascal }}Id::generate() })
.await;
assert!(result.is_err());
assert_eq!(result.unwrap_err().to_string(), "{{ snake }}.repository_error");
}
}