안녕하세요 러스트조빱이에요
trait의 구현체의 동작이 모두 똑같을 때 이미 작성되어있는 테스트 코드를 재활용하고 싶어서 생각하다가 잘 돼서 조빱이지만 글 써봐요
#[derive(Debug, PartialEq)]
struct User {
username: String,
}
trait UserRepository {
fn get_user_by_username(&self, username: String) -> Option<&User>;
}
struct InMemoryUserRepository {
inner: Vec<User>,
}
impl UserRepository for InMemoryUserRepository {
fn get_user_by_username(&self, username: String) -> Option<&User> {
self.inner.iter().find(|user| user.username == username)
}
}
서버를 만들고 있다고 가정하고, 처음에는 테스트만 하면 되기 때문에 인메모리로도 충분해요.
그런데 점차 개발이 진행되고, 데이터 베이스를 사용해야하는 시점이 왔어요.
struct DatabaseUserRepository {
inner: HashMap<String, User>,
}
impl UserRepository for DatabaseUserRepository {
fn get_user_by_username(&self, username: String) -> Option<&User> {
self.inner.get(&username)
}
}
구현했어요. 테스트도 해야돼요.
trait TestUserRepository: UserRepository + From<Vec<User>> {
fn test_get_user_by_username() {
let user_repository = Self::from(fake_users());
let actual = user_repository.get_user_by_username("홍길동".to_string());
let expected = User {
username: "홍길동".to_string(),
};
assert_eq!(actual, Some(&expected));
}
}
impl From<Vec<User>> for DatabaseUserRepository {
fn from(users: Vec<User>) -> Self {
let mut inner = HashMap::default();
for user in users {
let username = user.username.clone();
inner.insert(username, user);
}
Self { inner }
}
}
impl From<Vec<User>> for InMemoryUserRepository {
fn from(users: Vec<User>) -> Self {
Self { inner: users }
}
}
impl TestUserRepository for InMemoryUserRepository {}
impl TestUserRepository for DatabaseUserRepository {}
TestUserRepository trait은 UserRepository와 From을 구현하게해서 테스트에서 해당 구현체를 생성할 수 있어요.
그런 다음 TestUserRepository trait을 각각 Repository에 구현해줘요.
mod inmemory {
use super::InMemoryUserRepository;
use super::TestUserRepository;
#[test]
fn test_get_user_by_username() {
InMemoryUserRepository::test_get_user_by_username()
}
}
mod database {
use super::DatabaseUserRepository;
use super::TestUserRepository;
#[test]
fn test_get_user_by_username() {
DatabaseUserRepository::test_get_user_by_username()
}
}
이렇게 해주면 이미 작성돼있는 테스트 코드를 재활용할 수 있어요.
댓글 0