Rust size birkaç yüz satırda hızlı, tür güvenli bir HTTP sunucusu sunar. Ancak bu sunucuyu test etmek için size hızlı bir geri bildirim döngüsü sağlamaz. Derleme döngüsü uzundur, `cargo test` tek bir özellik değişikliğinde her şeyi yeniden çalıştırır ve çoğu Rust HTTP çerçevesi, her uç nokta için henüz bir kez bile çağırmadan önce ayrı bir entegrasyon testi yazmanızı gerektirir. Sadece bir ikili değil, bir API yayınlamak istiyorsanız, Rust araç zincirinin dışında yer alan ve çalışan sunucuyla iletişim kuran bir araca ihtiyacınız var.
Bu kılavuz, Apidog içinde tüm Rust API test iş akışını anlatmaktadır: Apidog'u Axum veya Actix sunucunuza yönlendirme, uç noktalarınıza karşı istekler oluşturma, Serde ile serileştirilmiş JSON'ı doğrulama, JWT kimlik doğrulamasını yönetme, siz işleyiciyi bitirirken ön ucun ilerlemesi için uç noktaları taklit etme (mock'lama) ve tüm bunları bir CI test senaryosu olarak paketleme. Sonunda, `cargo build --release` tamamlanmadan sözleşme kaymasını yakalayan yeniden kullanılabilir bir Apidog projeniz olacak.
Postman veya `curl` iş akışından geliyorsanız, Apidog'un tasarım öncelikli özelliklerini de ücretsiz olarak elde edersiniz: kaydedilmiş isteklerinizden oluşturulan bir OpenAPI spesifikasyonu, paylaşılabilir mock (sahte) URL'ler ve ekip ortamları. Ayrı bir okuma için Postman geçiş hikayesini geçin; bu gönderi Rust'a odaklanmaya devam ediyor.
TL;DR
- Rust sunucunuzu yerel olarak çalıştırın (bir Axum veya Actix-web projesine karşı `cargo run`), `http://localhost:3000` temel URL'sini bir Apidog ortamı olarak ekleyin ve herhangi bir sırrı değişken olarak saklayın.
- `GET /healthz`'ye karşı ilk isteği oluşturun, kaydedin ve klasördeki her işleyici arasında kimlik doğrulamasını ve temel URL'yi yeniden kullanın.
- JSON uç noktaları için Serde yapınızı Apidog'un gövde düzenleyicisine yapıştırın ve her göndermeden sonra çalışan Test komut dosyalarıyla yanıt şeklini doğrulayın.
- Korumalı rotalar için bir kez JWT oluşturun, `{{token}}` olarak kaydedin ve her testin miras alması için klasör düzeyinde Bearer kimlik doğrulamasını uygulayın.
- Bitmemiş Rust işleyicilerini Apidog'da taklit edin, böylece ön uç ekibiniz işleyici düzgün bir şekilde derlenmeden önce gerçek yanıtları render edebilir.
- Çalışma kümesini bir Test Senaryosu olarak kaydedin, dışa aktarın ve `apidog-cli` ile CI'da çalıştırın. Bir işleyiciyi etkileyen her PR, birleştirmeden önce bir sözleşme kontrolü alır.
Neden Rust API'sini Rust araç zincirinin dışında test etmelisiniz?
`cargo test` iyidir. Aynı zamanda yavaştır, Rust dışındaki ekip arkadaşları için anlaşılmazdır ve HTTP yerine kod üzerine kuruludur. İşleyicinizin doğru durum kodunu, doğru JSON yapısını, doğru başlıkları ve giriş bozuk olduğunda doğru hata mesajını döndürdüğünü doğrulamak istiyorsanız, her durum için yeni bir `tower::ServiceExt::oneshot` çağrısı yazarsınız. Ardından işleyici değiştikçe bu testi sürdürürsünüz. Sonra ön ucun bir mock'a (sahte) erişebilmesi için onu JavaScript'te tekrar yazarsınız.
Apidog, çalışan sunucunun üzerinde tek bir sözleşme katmanı sunar. İstek bir kez yaşar. Doğrulamalar isteğin yanında bulunur. Ön uç ekip arkadaşları aynı projeyi açar ve sizinle aynı istekleri görür. Üç hafta sonra Serde bir `#[serde(rename_all = "camelCase")]` niteliği aldığında, bozulan test üretim ortamına gönderilen değil, Apidog'daki test olur.
Apidog'u bir Rust iş akışına eklemek için üç somut neden:
- Sözleşme kontrolleri derlemeden ayrılır. Apidog, çalışan bir ikiliye karşı çalışır. Uç noktanızın hala `200` döndürdüğünü doğrulamak için `rustc`'yi beklemeyi bırakırsınız.
- Mock'lar paylaşılabilir. Başka bir zaman dilimindeki bir ön uç geliştiricisi, "işleyici henüz bitmedi" diyen bir Slack mesajı yerine doğru JSON'ı döndüren bir URL alır.
- OpenAPI ücretsiz. Apidog, kaydedilmiş isteklerden bir OpenAPI 3.1 belgesi oluşturabilir. Bunu, her rota için bir `utoipa` veya `aide` ek açıklaması yazmadan türü belirlenmiş bir istemci isteyen herkese verebilirsiniz.
Adım 1: Rust sunucunuzu bir Apidog ortamı olarak ekleyin
Rust API'nizi başlatın. Bir Axum projesi için başlangıç kodu şöyledir:
use axum::{routing::get, Router};
use tokio::net::TcpListener;
#[tokio::main]
async fn main() {
let app = Router::new().route("/healthz", get(|| async { "ok" }));
let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Apidog'u açın, yeni bir proje oluşturun, ardından Ortam Yönetimi'ni (sağ üst açılır menü) açın ve `Rust Local` adında bir ortam ekleyin:
| Değişken | Değer |
|---|---|
baseUrl |
http://localhost:3000 |
token |
şimdilik boş bırakın |
apiVersion |
v1 |
Dağıtılmış temel URL ile `Rust Staging` adında ikinci bir ortam ekleyin. Apidog, değişkenleri ortama göre kapsar, böylece tek bir açılır menü tıklamasıyla yerelden hazırlık ortamına geçiş yapabilirsiniz. Kaydedilmiş istekler arasında bul-değiştir yapmanıza gerek kalmaz.
Adım 2: İlk uç noktaya istek gönderin
Proje içinde `Rust API` adında bir klasör oluşturun, ardından yeni bir istek:
- Metot: `GET`
- URL: `{{baseUrl}}/healthz`
Gönder'e tıklayın. Sunucunuz çalışıyorsa, gövdesi `ok` olan bir `200` yanıtı alırsınız. Bunu `health-check` olarak kaydedin. Bu, mümkün olan en basit duman testidir ve daha ilginç bir şey yazmadan önce ortamın ve temel URL'nin çalıştığını doğrular.
Bağlantı reddedildi hatası alırsanız, sunucunuz `0.0.0.0`'a bağlı değildir veya port yanlıştır. Rust'ın varsayılan `TcpListener::bind("127.0.0.1:3000")` ayarı, farklı bir arayüzde `localhost`'a çözümleyen her şeyden gelen istekleri reddeder; yerel geliştirme için `0.0.0.0`'a bağlanın, böylece Apidog ve Docker kapsayıcıları ona ulaşabilir.
Adım 3: Serde ile JSON istek ve yanıtını test edin
En yaygın Rust API şekli, bir Serde yapısı tarafından desteklenen, JSON girişi ve JSON çıkışı olan bir işleyicidir. Bir `POST /users` rotası ekleyin:
use axum::{extract::Json, routing::post, Router};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct CreateUser {
name: String,
email: String,
}
#[derive(Serialize)]
struct User {
id: u64,
name: String,
email: String,
}
async fn create_user(Json(payload): Json<CreateUser>) -> Json<User> {
Json(User { id: 1, name: payload.name, email: payload.email })
}
let app = Router::new().route("/users", post(create_user));
Apidog'da bir istek oluşturun:
- Metot: `POST`
- URL: `{{baseUrl}}/users`
- Gövde (JSON):
{
"name": "Ada Lovelace",
"email": "ada@example.com"
}
Gönderin. `User` JSON'ını geri alırsınız. `create-user` olarak kaydedin.
Şimdi Testler sekmesini açın ve doğrulamalar ekleyin:
pm.test("Status is 200", () => {
pm.expect(pm.response.code).to.eql(200);
});
pm.test("Body has id, name, email", () => {
const body = pm.response.json();
pm.expect(body).to.have.property("id");
pm.expect(body.name).to.eql("Ada Lovelace");
pm.expect(body.email).to.match(/^[^@]+@[^@]+$/);
});
Bir dahaki sefere biri yapıya `#[serde(rename_all = "camelCase")]` eklediğinde ve yanıt şekliniz `user_id`'den `userId`'ye döndüğünde, bu değişiklik gönderilmeden önce bu test başarısız olur. Bu, Apidog'un size verdiği bir sözleşmedir; `cargo test` bunu yapmaz, çünkü `cargo test` Rust kodunuzu Rust türlerinize karşı çalıştırır ve her iki şekille de sorunsuz bir şekilde geçerdi.
Adım 4: Serde ret durumlarını kapsayın
Rust JSON işlemenin ilginç yanı, Serde'nin hatalı girdi ile ne yaptığıdır. Varsayılan olarak Axum, ayrıntısız bir `422 İşlenemeyen Varlık` döndürür. Şemayı kasıtlı olarak bozan üç istek oluşturun:
| İstek | Gövde | Beklenen |
|---|---|---|
create-user-missing-email |
{ "name": "Ada" } |
422, gövde `email` alanı eksik diyor |
create-user-extra-field |
{ "name": "Ada", "email": "a@b.c", "admin": true } |
`#[serde(deny_unknown_fields)]` yoksa `200`; aksi takdirde `422` |
create-user-wrong-type |
{ "name": 1, "email": "a@b.c" } |
422, `geçersiz tür: tam sayı` diyor |
Testlerde her durum kodunu doğrulayın. Bu, gerçek doğrulama politikanızı belgelemenin en uygun yoludur. `deny_unknown_fields`'ı daha sonra açarsanız, ikinci test kırmızıya döner ve size genel sözleşmenin değiştiğini söyler.
Adım 5: JWT korumalı rotaları test edin
Çoğu üretim Rust API'si, işleyicileri bir kimlik doğrulama ara yazılımının arkasına gizler. Axum'un `axum-extra` JWT çıkarıcısı yaygın bir desendir:
use axum_extra::extract::cookie::PrivateCookieJar;
use jsonwebtoken::{decode, DecodingKey, Validation};
async fn me(jar: PrivateCookieJar) -> Result<Json<User>, StatusCode> {
let token = jar.get("token").ok_or(StatusCode::UNAUTHORIZED)?;
let claims = decode::<Claims>(token.value(), &DecodingKey::from_secret(b"secret"), &Validation::default())
.map_err(|_| StatusCode::UNAUTHORIZED)?;
Ok(Json(User { id: claims.claims.sub, name: "Ada".into(), email: "ada@example.com".into() }))
}
Apidog'da, her test çalışmasında JWT'yi manuel olarak oluşturmanıza gerek yoktur. Klasörde bir Ön-İstek Betiği oluşturun:
const jwt = require("jsonwebtoken");
const token = jwt.sign(
{ sub: 1, exp: Math.floor(Date.now() / 1000) + 3600 },
"secret"
);
pm.environment.set("token", token);
Klasör ayarlarını açın, Kimlik Doğrulama'yı (Auth) Bearer Token olarak ayarlayın, değer `{{token}}`. Klasördeki her istek artık yeni bir JWT imzalar ve sunar. Süresi geçmiş jeton hataları test çalışmalarınızdan kaybolur. Doğrulama tarafında daha derinlemesine bir inceleme için, API'lerde JWT kimlik doğrulamasını nasıl test edeceğinize bakın.
Adım 6: Akış ve Sunucu Tarafından Gönderilen Olayları Test Edin
Rust web çerçeveleri birinci sınıf akışa sahiptir. Axum'un `Sse` yanıtı bir `futures::Stream`'i sarmalar ve `text/event-stream` parçacıkları yayar. Ağ formatı, bağlantının kapanması veya açık bir tamamlandı olayı ile sonlanan her kare için `data: { ... }\n\n` şeklindedir.
Bunu tüketen bir istek, herhangi bir GET isteğiyle aynı görünür, ancak `Content-Type` `text/event-stream` olduğunda Apidog'daki yanıt paneli akış moduna geçer. Her kareyi gelir gelmez, zaman damgalarıyla birlikte görürsünüz. Bu, bir geri basınç sorununu veya eksik bir temizlemeyi (flush) ayıklarken ihtiyacınız olan görünümdür.
Doğrulanacaklar:
- İlk parça, reklamını yaptığınız SLA içinde ulaşır. Apidog, akış panelinde parça başına gecikmeyi gösterir.
- Bağlantı kapanmadan önce belirli bir olay adı tetiklenir (örneğin, `event: done`).
- Toplam akış süresi sınırlıdır. `while let Some(event) = stream.next().await` döngüsünden çıkmayı unutan bir işleyici sonsuza dek akış yapar; Apidog bunu gösterecek ve testi başarısız kılmak için istek ayarlarında kesin bir zaman aşımı belirleyebilirsiniz.
Uç noktanız SSE yerine WebSockets kullanıyorsa, Apidog'un ayrı bir WebSocket istek türü vardır. Desen aynıdır: bağlantıyı bir kez kurun, mesaj sırasını kaydedin, yanıtlarda doğrulama yapın.
Adım 7: Paralel ön uç geliştirme için Rust API'sini mock'layın (taklit edin)
Ön uç nadiren Rust derleme süreleri tarafından engellenir. Henüz var olmayan işleyiciler tarafından engellenir. Apidog mock'ları, işleyici gönderilmeden önce sizin ve ön ucun anlaştığı sözleşmeyi döndüren sabit bir URL yayınlamanıza olanak tanır.
`create-user`'a sağ tıklayın, Akıllı Mock'u seçin ve etkinleştirin. Apidog artık `https://mock.apidog.com/m1/<projectId>/users` adresinde sentetik bir `User` yanıtı sunar. Mock gövdesi, kaydedilmiş örneğinizle eşleşir. Mock URL'si aynı gövde şeklini kabul eder, böylece ön uç gerçek Rust sunucusuymuş gibi ona karşı `POST` yapabilir.
Dinamik mock'lar için Gelişmiş Mock'a geçin ve bir betik yazın:
return {
id: Math.floor(Math.random() * 10000),
name: body.name,
email: body.email,
createdAt: new Date().toISOString()
};
Bu mock, ön ucun gönderdiği her şeye, oluşturulmuş bir `id` ve zaman damgasıyla yanıt verir. Rust işleyicisi hazır olduğunda, ön uç temel URL'sini tekrar `http://localhost:3000`'e çevirir ve başka hiçbir şey değişmez. Bu desen hakkında daha fazla bilgi için ekip, bir Spring Boot API'si oluşturmayı ve test etmeyi ve genel API test iş akışını da ele almaktadır; aynı fikir, farklı çalışma zamanları.
Adım 8: CI test senaryosu olarak kaydedin
Apidog Test Senaryoları, paylaşılan değişkenlerle istekleri zincirler ve onları başsız (headless) çalıştırır. Bir senaryo oluşturun:
- `health-check`, `200` doğrula.
- `create-user`, `200` doğrula, `body.id`'yi bir değişkene yakala.
- `create-user-missing-email`, `422` doğrula.
- `me` (JWT ön isteği ile), `200` doğrula ve dönen `id`'nin yakalanan `id` ile eşleştiğini doğrula.
- SSE isteği, akışın 5 saniye içinde tamamlandığını doğrula.
Senaryoyu JSON olarak dışa aktarın, `tests/apidog/` altına deponuza kaydedin ve CI'dan çağırın:
- name: API sözleşme testlerini çalıştır
run: |
cargo build --release
./target/release/myserver &
sleep 2
apidog-cli run tests/apidog/contract.json --env "Rust Local"
Bir işleyiciyi etkileyen her PR, artık tam sözleşme paketiyle çalışan bir Rust ikilisine karşı çalışır. Bir Serde yeniden adlandırması, bir durum kodu değişikliği veya bir JWT doğrulama ayarı genel şekli bozarsa, CI birleştirme düğmesi yeşile dönmeden önce bunu yakalar.
Adım 9: Kaydedilmiş isteklerden OpenAPI oluşturun
İstek kümesi kararlı olduğunda, Apidog'un Dışa Aktarma menüsünü açın ve OpenAPI 3.1'i seçin. Gönderdiğiniz gövdeler örnek olarak dahil olmak üzere, kaydedilen her isteği kapsayan bir spesifikasyon belgesi alırsınız. Bunu, türü belirlenmiş bir istemci (TypeScript, Swift, Kotlin, Python) oluşturan herkese verin ve onlar, altı ay önce birisinin elle `.yaml` dosyasına yazdığıyla değil, Rust sunucunuzun bugün döndürdüğüyle eşleşen bir sözleşme elde ederler.
Spesifikasyonun Rust deponuza işlenmesini istiyorsanız, CI'dan `apidog-cli export` komutunu çalıştırın ve bunu `openapi.json`'a yazın. Bir sonraki `cargo build` değişmez, ancak API'nizin her tüketicisi diskte gerçeği elde eder.
SSS
Apidog hem Axum hem de Actix-web ile çalışır mı? Evet. Apidog HTTP ile konuşur, Rust ile değil. Bir isteğe yanıt veren her şey (Axum, Actix-web, Rocket, Warp, Poem, Loco) aynı şekilde çalışır. Tek Rust'a özgü husus, yerel testler için `127.0.0.1` yerine `0.0.0.0`'a bağlanmaktır.
Panikleyen işleyicileri nasıl test ederim? Sunucunuzu yönlendiricinin önüne `tower-http`'nin `CatchPanicLayer`'ını koyarak çalıştırın. Panik, JSON gövdesiyle bir `500`'e dönüşür. Panik yolunu tetikleyen bir Apidog isteği oluşturun ve `500`'ü doğrulayın. Panikleri sarmazsanız, bağlantı kesilir ve Apidog bir ağ hatası bildirir, bu da geçerli bir sözleşme testidir.
Apidog'u Docker'daki bir Rust ikilisine karşı çalıştırabilir miyim? Evet. `baseUrl`'i kapsayıcının açıkta kalan portuna yönlendirin ve işiniz biter. Kapsayıcı Docker Compose içinde çalışıyorsa, Apidog çalıştırıcınıza aynı ağı verin veya ana bilgisayarın eşlenmiş portunu kullanın.
gRPC ne olacak? Apidog'un bir gRPC istek türü vardır. `.proto` dosyalarınızı içe aktarın, bir hizmet ve metot seçin, istek yükünü doldurun ve gönderin. Kimlik doğrulama, ortamlar ve test senaryoları deseni REST ile aynıdır.
Test senaryosu `cargo test`'in yerini mi alır? Hayır. Rust kodunuz için birim testleri Rust'ta kalır. Apidog çalışan yüzeyi test eder: HTTP sözleşmesini. İki katman farklı hataları yakalar. Bir birim testi bozuk bir fonksiyonu yakalar; bir Apidog testi bozuk bir yanıt şeklini, eksik bir CORS başlığını veya `400`'den `422`'ye dönüşen bir durumu yakalar. İkisini de istersiniz.
Apidog Rust açık kaynak projeleri için ücretsiz mi? Evet. Apidog istemcisi bireyler ve küçük ekipler için ücretsizdir. Test senaryoları, mock'lar ve OpenAPI dışa aktarma ücretsiz katmanın bir parçasıdır. Herkese açık bir Rust API'si sürdürüyorsanız, depoda proje dosyasını göndererek kopyalayan herkesin test paketini almasını sağlayabilirsiniz.
Özet
Rust API'leri, derleyiciyi beklemeyen bir geri bildirim döngüsünü hak eder. Apidog'daki bir istek koleksiyonu size bu döngüyü sunar: gerçek HTTP, gerçek doğrulamalar, ön uç için gerçek mock'lar ve canlı ikiliye karşı çalışan bir CI senaryosu. Yukarıdaki istekleri bir kez oluşturun ve Axum veya Actix işleyicinizdeki her gelecekteki değişiklik, çalışma zamanı sürprizi yerine kontrollü bir test çalışmasına dönüşür.
Apidog'u indirin ve Rust sunucunuza yönlendirin. Kurulum on dakikadan az sürer. Getirisi, sizin kontrol ettiğiniz, `cargo`'dan bağımsız bir sözleşme ve işleyicinin ne zaman biteceğini sormayı bırakan bir ön uç ekibidir.
