Skip to content
This repository was archived by the owner on Nov 21, 2024. It is now read-only.

Commit 1081868

Browse files
authored
test: Introduce mocking framework (#168)
1 parent b661611 commit 1081868

File tree

13 files changed

+460
-72
lines changed

13 files changed

+460
-72
lines changed

Cargo.lock

Lines changed: 74 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ thiserror = "1.0.41"
2626
diesel = { version = "2.1.0", features = ["sqlite", "r2d2", "returning_clauses_for_sqlite_3_35"] }
2727
reqwest = {version = "0.11.18", features = ["json"] }
2828
nanoid = "0.4.0"
29+
faux = "0.1.9"
2930

3031

3132

server/src/controller/mod.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@ mod project;
77

88
use crate::service::auth::AuthService;
99
use crate::service::function::FunctionService;
10-
use crate::service::{project::ProjectService, user::UserService};
10+
use crate::service::project::ProjectService;
1111
use crate::wasmstore::WasmStore;
1212
use axum::{extract::FromRef, middleware, Router};
1313

1414
#[derive(Debug, Clone)]
1515
pub struct AppState {
1616
auth: AuthService,
17-
users: UserService,
1817
projects: ProjectService,
1918
functions: FunctionService,
2019
wasmstore: WasmStore,
@@ -23,14 +22,12 @@ pub struct AppState {
2322
impl AppState {
2423
pub fn new(
2524
auth: AuthService,
26-
users: UserService,
2725
projects: ProjectService,
2826
functions: FunctionService,
2927
wasmstore: WasmStore,
3028
) -> Self {
3129
Self {
3230
auth,
33-
users,
3431
projects,
3532
functions,
3633
wasmstore,
@@ -50,12 +47,6 @@ impl FromRef<AppState> for AuthService {
5047
}
5148
}
5249

53-
impl FromRef<AppState> for UserService {
54-
fn from_ref(app_state: &AppState) -> UserService {
55-
app_state.users.clone()
56-
}
57-
}
58-
5950
impl FromRef<AppState> for ProjectService {
6051
fn from_ref(app_state: &AppState) -> ProjectService {
6152
app_state.projects.clone()

server/src/github.rs

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use serde::Deserialize;
88
const GITHUB_API_USER: &str = "https://api.github.com/user";
99
const GITHUB_API_EMAIL: &str = "https://api.github.com/user/emails";
1010

11+
#[derive(Debug, Clone)]
1112
pub struct GithubUser {
1213
pub id: i32,
1314
pub email: String,
@@ -25,51 +26,67 @@ struct Email {
2526
primary: bool,
2627
}
2728

28-
pub async fn get_user(access_token: String) -> anyhow::Result<GithubUser> {
29-
let client = reqwest::Client::new();
30-
let headers = create_headers(&access_token)?;
29+
#[cfg_attr(test, faux::create)]
30+
#[derive(Debug, Clone)]
31+
pub struct GithubClient {
32+
client: Client,
33+
}
3134

32-
let user_infos = get_user_infos(&client, headers.clone()).await?;
33-
let email = get_primary_email(&client, headers).await?;
35+
#[cfg_attr(test, faux::methods)]
36+
impl GithubClient {
37+
pub fn new() -> Self {
38+
Self {
39+
client: reqwest::Client::new(),
40+
}
41+
}
3442

35-
Ok(GithubUser {
36-
id: user_infos.id,
37-
email: email.email,
38-
access_token,
39-
})
40-
}
43+
pub async fn get_user(&self, access_token: String) -> anyhow::Result<GithubUser> {
44+
let headers = self.create_headers(&access_token)?;
4145

42-
async fn get_user_infos(client: &Client, headers: HeaderMap) -> anyhow::Result<User> {
43-
let user = client
44-
.get(GITHUB_API_USER)
45-
.headers(headers)
46-
.send()
47-
.await?
48-
.json()
49-
.await?;
46+
let user_infos = self.get_user_infos(headers.clone()).await?;
47+
let email = self.get_primary_email(headers).await?;
5048

51-
Ok(user)
52-
}
49+
Ok(GithubUser {
50+
id: user_infos.id,
51+
email: email.email,
52+
access_token,
53+
})
54+
}
5355

54-
async fn get_primary_email(client: &Client, headers: HeaderMap) -> anyhow::Result<Email> {
55-
let emails: Vec<Email> = client
56-
.get(GITHUB_API_EMAIL)
57-
.headers(headers)
58-
.send()
59-
.await?
60-
.json()
61-
.await?;
62-
63-
let email = emails.into_iter().find(|email| email.primary).unwrap();
64-
Ok(email)
65-
}
56+
async fn get_user_infos(&self, headers: HeaderMap) -> anyhow::Result<User> {
57+
let user = self
58+
.client
59+
.get(GITHUB_API_USER)
60+
.headers(headers)
61+
.send()
62+
.await?
63+
.json()
64+
.await?;
65+
66+
Ok(user)
67+
}
68+
69+
async fn get_primary_email(&self, headers: HeaderMap) -> anyhow::Result<Email> {
70+
let emails: Vec<Email> = self
71+
.client
72+
.get(GITHUB_API_EMAIL)
73+
.headers(headers)
74+
.send()
75+
.await?
76+
.json()
77+
.await?;
78+
79+
let email = emails.into_iter().find(|email| email.primary).unwrap();
80+
Ok(email)
81+
}
6682

67-
fn create_headers(access_token: &str) -> anyhow::Result<HeaderMap> {
68-
let mut headers = HeaderMap::new();
69-
headers.insert(USER_AGENT, "noops-server".parse()?);
70-
headers.insert(AUTHORIZATION, format!("Bearer {}", access_token).parse()?);
71-
headers.insert(ACCEPT, "application/vnd.github+json".parse()?);
72-
headers.insert("X-GitHub-Api-Version", "2022-11-28".parse()?);
83+
fn create_headers(&self, access_token: &str) -> anyhow::Result<HeaderMap> {
84+
let mut headers = HeaderMap::new();
85+
headers.insert(USER_AGENT, "noops-server".parse()?);
86+
headers.insert(AUTHORIZATION, format!("Bearer {}", access_token).parse()?);
87+
headers.insert(ACCEPT, "application/vnd.github+json".parse()?);
88+
headers.insert("X-GitHub-Api-Version", "2022-11-28".parse()?);
7389

74-
Ok(headers)
90+
Ok(headers)
91+
}
7592
}

server/src/main.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ mod service;
99
mod wasmstore;
1010

1111
use axum::Server;
12-
use service::{
13-
auth::AuthService, function::FunctionService, project::ProjectService, user::UserService,
14-
};
12+
use github::GithubClient;
13+
use service::{auth::AuthService, function::FunctionService, project::ProjectService};
1514
use std::{net::SocketAddr, path::Path};
1615
use tower_http::trace::TraceLayer;
1716
use tracing_subscriber::{self, layer::SubscriberExt, util::SubscriberInitExt};
@@ -47,18 +46,11 @@ fn create_app_state(database_path: &Path, wasmstore_path: &Path) -> anyhow::Resu
4746
let (users, projects, functions) = repository::new(database_path);
4847
let wasmstore = wasmstore::WasmStore::new(wasmstore_path)?;
4948

50-
let auth_service = AuthService::new(users);
51-
let user_service = UserService::new();
49+
let auth_service = AuthService::new(GithubClient::new(), users);
5250
let project_service = ProjectService::new(projects.clone(), functions.clone());
5351
let function_service = FunctionService::new(projects, functions, wasmstore.clone());
5452

55-
let state = AppState::new(
56-
auth_service,
57-
user_service,
58-
project_service,
59-
function_service,
60-
wasmstore,
61-
);
53+
let state = AppState::new(auth_service, project_service, function_service, wasmstore);
6254

6355
Ok(state)
6456
}

server/src/repository/function.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,13 @@ impl From<Function> for GetFunctionDTO {
3939
}
4040
}
4141

42+
#[cfg_attr(test, faux::create)]
4243
#[derive(Debug, Clone)]
4344
pub struct FunctionRepository {
4445
pool: Pool<ConnectionManager<SqliteConnection>>,
4546
}
4647

48+
#[cfg_attr(test, faux::methods)]
4749
impl Repository<Function> for FunctionRepository {
4850
fn new(pool: Pool<ConnectionManager<SqliteConnection>>) -> Self {
4951
Self { pool }
@@ -81,10 +83,10 @@ impl Repository<Function> for FunctionRepository {
8183
}
8284
}
8385

86+
#[cfg_attr(test, faux::methods)]
8487
impl FunctionRepository {
8588
pub fn belonging_to(&self, project: &Project) -> anyhow::Result<Vec<Function>> {
8689
let mut connection = self.pool.get()?;
87-
8890
let functions = Function::belonging_to(project).load::<Function>(&mut connection)?;
8991
Ok(functions)
9092
}
@@ -133,9 +135,9 @@ mod tests {
133135
fn setup() -> anyhow::Result<(TempDir, FunctionRepository)> {
134136
let temp_dir = tempdir()?;
135137
let pool = create_pool(&temp_dir.path().join(DATABASE_NAME));
138+
let mut connection = pool.get()?;
136139
let projects = FunctionRepository::new(pool);
137140
let migrations = FileBasedMigrations::find_migrations_directory_in_path("./server")?;
138-
let mut connection = projects.pool.get()?;
139141
connection.run_pending_migrations(migrations).unwrap();
140142
Ok((temp_dir, projects))
141143
}

server/src/repository/project.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ impl Project {
3131
}
3232
}
3333

34+
#[cfg_attr(test, faux::create)]
3435
#[derive(Debug, Clone)]
3536
pub struct ProjectRepository {
3637
pool: Pool<ConnectionManager<SqliteConnection>>,
3738
}
3839

40+
#[cfg_attr(test, faux::methods)]
3941
impl Repository<Project> for ProjectRepository {
4042
fn new(pool: Pool<ConnectionManager<SqliteConnection>>) -> Self {
4143
Self { pool }
@@ -71,6 +73,7 @@ impl Repository<Project> for ProjectRepository {
7173
}
7274
}
7375

76+
#[cfg_attr(test, faux::methods)]
7477
impl ProjectRepository {
7578
pub fn belonging_to_by_name(
7679
&self,
@@ -112,9 +115,9 @@ mod tests {
112115
fn setup() -> anyhow::Result<(TempDir, ProjectRepository)> {
113116
let temp_dir = tempdir()?;
114117
let pool = create_pool(&temp_dir.path().join(DATABASE_NAME));
118+
let mut connection = pool.get()?;
115119
let projects = ProjectRepository::new(pool);
116120
let migrations = FileBasedMigrations::find_migrations_directory_in_path("./server")?;
117-
let mut connection = projects.pool.get()?;
118121
connection.run_pending_migrations(migrations).unwrap();
119122
Ok((temp_dir, projects))
120123
}

0 commit comments

Comments
 (0)