Skip to content

Instantly share code, notes, and snippets.

@mishbah
Last active May 28, 2024 00:13
Show Gist options
  • Save mishbah/42ad99462210c9fc5e9f194ef18d9a0a to your computer and use it in GitHub Desktop.
Save mishbah/42ad99462210c9fc5e9f194ef18d9a0a to your computer and use it in GitHub Desktop.
Contoh `mockall` di actix-web. sumber: Claude 3 Haiku

Berikut adalah contoh penggunaan mockall untuk mocking dependencies pada Actix-Web, beserta unit test:

  1. Buat sebuah service yang akan diuji, misalnya user_service.rs:
use actix_web::{get, web, Responder};
use mockall::predicate::*;
use mockall::MockResult;

#[derive(Debug)]
pub struct UserService {
    pub db: Box<dyn UserRepository>,
}

#[get("/users/{id}")]
async fn get_user(
    web::Path(id): web::Path<String>,
    service: web::Data<UserService>,
) -> impl Responder {
    let user = service.db.get_user(&id).await.unwrap_or_else(|_| None);
    format!("User: {:?}", user)
}

pub trait UserRepository {
    async fn get_user(&self, id: &str) -> Result<Option<User>, anyhow::Error>;
}

#[derive(Debug)]
pub struct User {
    pub id: String,
    pub name: String,
}
  1. Buat mock untuk UserRepository menggunakan mockall:
use mockall::mock;

mock! {
    pub UserRepository {
        async fn get_user(&self, id: &str) -> Result<Option<User>, anyhow::Error>;
    }
}
  1. Tulis unit test yang menggunakan mock UserRepository:
use actix_web::{test, web, App};
use mockall::predicate::*;
use user_service::{get_user, User, UserRepository, UserService};

#[actix_web::test]
async fn test_get_user() {
    let mut mock_repo = MockUserRepository::new();
    mock_repo
        .expect_get_user()
        .with(eq("123"))
        .returning(|| Ok(Some(User {
            id: "123".to_string(),
            name: "John Doe".to_string(),
        })));

    let app = test::init_service(
        App::new()
            .app_data(web::Data::new(UserService {
                db: Box::new(mock_repo),
            }))
            .service(get_user),
    )
    .await;

    let req = test::TestRequest::with_path("/users/123").to_request();
    let resp = test::call_service(&app, req).await;
    assert!(resp.status().is_success());
    let body = test::read_body(resp).await;
    assert_eq!(body, b"User: User { id: \"123\", name: \"John Doe\" }");
}

Dalam contoh ini, kita membuat sebuah mock UserRepository menggunakan mockall. Kemudian, kita mengkonfigurasi mock untuk mengembalikan data yang diharapkan ketika metode get_user dipanggil dengan parameter "123".

Selanjutnya, kita membuat sebuah aplikasi Actix-Web yang menggunakan UserService dengan mock UserRepository, dan menjalankan unit test untuk memastikan bahwa endpoint /users/{id} mengembalikan respons yang diharapkan.

Dengan menggunakan mockall, Anda dapat dengan mudah menyediakan mock dependencies untuk unit test, sehingga Anda dapat menguji logika aplikasi tanpa harus bergantung pada implementasi yang sebenarnya.

Sedangkan untuk file Cargo.toml

[package]
name = "actix-web-mockall-example"
version = "0.1.0"
edition = "2021"

[dependencies]
actix-web = "4.2.1"
mockall = "0.11.0"
anyhow = "1.0.68"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment