0 Tage Serie
rust / expert
Snippet

Entwurf von Compile-Time-Mocking-Schnittstellen für Unit-Tests

Dieses Snippet zeigt, wie Unit-Tests unter Verwendung von Trait-basierter Dependency Injection für Mocking entworfen werden. Durch die Entkopplung der Datenbankoperationen über ein Trait erstellen wir ein leichtgewichtiges Mock-Objekt zur Kompilierzeit im Testmodul, um erwartete Eingaben und Antworten ohne externe Frameworks zu überprüfen.

snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
pub trait Database {
fn fetch_user_role(&self, user_id: u32) -> Result<String, &'static str>;
}
pub struct UserService<'a, D: Database> {
pub db: &'a D,
}
impl<'a, D: Database> UserService<'a, D> {
pub fn is_admin(&self, user_id: u32) -> bool {
self.db.fetch_user_role(user_id)
.map(|role| role == "Admin")
.unwrap_or(false)
}
}
#[cfg(test)]
mod tests {
use super::*;
struct MockDatabase {
expected_id: u32,
returned_role: Result<String, &'static str>,
}
impl Database for MockDatabase {
fn fetch_user_role(&self, user_id: u32) -> Result<String, &'static str> {
assert_eq!(user_id, self.expected_id);
self.returned_role.clone()
}
}
#[test]
fn test_admin_verification() {
let mock = MockDatabase {
expected_id: 42,
returned_role: Ok(String::from("Admin")),
};
let service = UserService { db: &mock };
assert!(service.is_admin(42));
}
}
Erklärung
1
pub trait Database
Deklariert ein Trait, das Datenbankoperationen darstellt, um Abhängigkeiten zu entkoppeln.
2
pub struct UserService<'a, D: Database>
Definiert einen Dienst, der über einen beliebigen Typ veränderlich ist, der das Database-Trait implementiert.
3
struct MockDatabase
Eine Mock-Struktur, die im Testmodul definiert ist und Test-Zusicherungen sowie Rückgabedaten enthält.
4
assert_eq!(user_id, self.expected_id);
Stellt sicher, dass der Dienst die Schnittstelle während des Tests mit den erwarteten Argumenten aufruft.