From ff3d847d98cc6f2ef3cdaddee30dafe6860e61f0 Mon Sep 17 00:00:00 2001 From: Luis Urrutia Date: Wed, 27 Aug 2025 16:05:16 +0200 Subject: [PATCH 1/3] refactor: Replace wiremock for mockito --- Cargo.lock | 41 --- Cargo.toml | 2 +- src/bootstrap/config_processor.rs | 97 +++--- src/services/google_cloud_kms/mod.rs | 227 ++++++------ src/services/jupiter/mod.rs | 91 ++--- src/services/notification/mod.rs | 80 +++-- src/services/provider/mod.rs | 25 +- .../signer/evm/google_cloud_kms_signer.rs | 96 ++++-- src/services/turnkey/mod.rs | 117 ++++--- src/services/vault/mod.rs | 324 +++++++++++------- 10 files changed, 599 insertions(+), 501 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 20392a284..ec557d879 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2943,23 +2943,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" -[[package]] -name = "deadpool" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ed5957ff93768adf7a65ab167a17835c3d2c3c50d084fe305174c112f468e2f" -dependencies = [ - "deadpool-runtime", - "num_cpus", - "tokio", -] - -[[package]] -name = "deadpool-runtime" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" - [[package]] name = "der" version = "0.7.10" @@ -5473,7 +5456,6 @@ dependencies = [ "uuid 1.18.0", "validator", "vaultrs", - "wiremock", "zeroize", ] @@ -11521,29 +11503,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "wiremock" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08db1edfb05d9b3c1542e521aea074442088292f00b5f28e435c714a98f85031" -dependencies = [ - "assert-json-diff", - "base64 0.22.1", - "deadpool", - "futures", - "http 1.3.1", - "http-body-util", - "hyper 1.7.0", - "hyper-util", - "log", - "once_cell", - "regex", - "serde", - "serde_json", - "tokio", - "url", -] - [[package]] name = "wit-bindgen-rt" version = "0.39.0" diff --git a/Cargo.toml b/Cargo.toml index d144b0a32..a5166ca08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,7 +97,7 @@ rand = "0.9.0" tempfile = "3.2" serial_test = "3.2" clap = { version = "4.4", features = ["derive"] } -wiremock = "0.6" + [[bin]] name = "openzeppelin-relayer" diff --git a/src/bootstrap/config_processor.rs b/src/bootstrap/config_processor.rs index 50dc3036e..3f7b4f4e8 100644 --- a/src/bootstrap/config_processor.rs +++ b/src/bootstrap/config_processor.rs @@ -370,10 +370,9 @@ mod tests { }, }; use actix_web::web::ThinData; + use mockito; use serde_json::json; use std::{sync::Arc, time::Duration}; - use wiremock::matchers::{body_json, header, method, path}; - use wiremock::{Mock, MockServer, ResponseTemplate}; fn create_test_app_state() -> AppState< MockJobProducerTrait, @@ -528,55 +527,67 @@ mod tests { // utility function to setup a mock AppRole login response async fn setup_mock_approle_login( - mock_server: &MockServer, + mock_server: &mut mockito::ServerGuard, role_id: &str, secret_id: &str, token: &str, - ) { - Mock::given(method("POST")) - .and(path("/v1/auth/approle/login")) - .and(body_json(json!({ + ) -> mockito::Mock { + mock_server + .mock("POST", "/v1/auth/approle/login") + .match_body(mockito::Matcher::Json(json!({ "role_id": role_id, "secret_id": secret_id }))) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ - "request_id": "test-request-id", - "lease_id": "", - "renewable": false, - "lease_duration": 0, - "data": null, - "wrap_info": null, - "warnings": null, - "auth": { - "client_token": token, - "accessor": "test-accessor", - "policies": ["default"], - "token_policies": ["default"], - "metadata": { - "role_name": "test-role" - }, - "lease_duration": 3600, - "renewable": true, - "entity_id": "test-entity-id", - "token_type": "service", - "orphan": true - } - }))) - .mount(mock_server) - .await; + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "request_id": "test-request-id", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": null, + "wrap_info": null, + "warnings": null, + "auth": { + "client_token": token, + "accessor": "test-accessor", + "policies": ["default"], + "token_policies": ["default"], + "metadata": { + "role_name": "test-role" + }, + "lease_duration": 3600, + "renewable": true, + "entity_id": "test-entity-id", + "token_type": "service", + "orphan": true + } + })) + .unwrap(), + ) + .create_async() + .await } #[tokio::test] async fn test_process_signer_vault() -> Result<()> { - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; - setup_mock_approle_login(&mock_server, "test-role-id", "test-secret-id", "test-token") - .await; - - Mock::given(method("GET")) - .and(path("/v1/secret/data/test-key")) - .and(header("X-Vault-Token", "test-token")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ + let _login_mock = setup_mock_approle_login( + &mut mock_server, + "test-role-id", + "test-secret-id", + "test-token", + ) + .await; + + let _secret_mock = mock_server + .mock("GET", "/v1/secret/data/test-key") + .match_header("X-Vault-Token", "test-token") + .with_status(200) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&json!({ "request_id": "test-request-id", "lease_id": "", "renewable": false, @@ -595,15 +606,15 @@ mod tests { "wrap_info": null, "warnings": null, "auth": null - }))) - .mount(&mock_server) + })).unwrap()) + .create_async() .await; let signer = SignerFileConfig { id: "vault-signer".to_string(), config: SignerFileConfigEnum::Vault(VaultSignerFileConfig { key_name: "test-key".to_string(), - address: mock_server.uri(), + address: mock_server.url(), namespace: Some("test-namespace".to_string()), role_id: PlainOrEnvValue::Plain { value: SecretString::new("test-role-id"), diff --git a/src/services/google_cloud_kms/mod.rs b/src/services/google_cloud_kms/mod.rs index e983b5547..53a34120e 100644 --- a/src/services/google_cloud_kms/mod.rs +++ b/src/services/google_cloud_kms/mod.rs @@ -429,9 +429,8 @@ mod tests { GoogleCloudKmsSignerKeyConfig, GoogleCloudKmsSignerServiceAccountConfig, SecretString, }; use alloy::primitives::utils::eip191_message; + use mockito::{Mock, ServerGuard}; use serde_json::json; - use wiremock::matchers::{header_exists, method, path_regex}; - use wiremock::{Mock, MockServer, ResponseTemplate}; fn create_test_config(uri: &str) -> GoogleCloudKmsSignerConfig { GoogleCloudKmsSignerConfig { @@ -493,90 +492,102 @@ mod tests { } // Mock setup helpers - async fn setup_mock_solana_public_key(mock_server: &MockServer) { - Mock::given(method("GET")) - .and(path_regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*/publicKey")) - .and(header_exists("Authorization")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ + async fn setup_mock_solana_public_key(mock_server: &mut ServerGuard) -> Mock { + mock_server + .mock("GET", mockito::Matcher::Regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*/publicKey".to_string())) + .match_header("Authorization", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&json!({ "pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAVyC+iqnSu0vo6R8x0sRMhintQtoZgcLOur1VyvCrdrs=\n-----END PUBLIC KEY-----\n", "algorithm": "ECDSA_P256_SHA256" - }))) - .mount(mock_server) - .await; + })).unwrap()) + .create_async() + .await } - async fn setup_mock_evm_public_key(mock_server: &MockServer) { - Mock::given(method("GET")) - .and(path_regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*/publicKey")) - .and(header_exists("Authorization")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ + async fn setup_mock_evm_public_key(mock_server: &mut ServerGuard) -> Mock { + mock_server + .mock("GET", mockito::Matcher::Regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*/publicKey".to_string())) + .match_header("Authorization", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&json!({ "pem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjJaJh5wfZwvj8b3bQ4GYikqDTLXWUjMh\nkFs9lGj2N9B17zo37p4PSy99rDio0QHLadpso0rtTJDSISRW9MdOqA==\n-----END PUBLIC KEY-----\n", // noboost "algorithm": "ECDSA_SECP256K1_SHA256" - }))) - .mount(mock_server) - .await; + })).unwrap()) + .create_async() + .await } - async fn setup_mock_sign_success(mock_server: &MockServer) { - Mock::given(method("POST")) - .and(path_regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*:asymmetricSign")) - .and(header_exists("Authorization")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ + async fn setup_mock_sign_success(mock_server: &mut ServerGuard) -> Mock { + mock_server + .mock("POST", mockito::Matcher::Regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*:asymmetricSign".to_string())) + .match_header("Authorization", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&json!({ "signature": "ZHVtbXlzaWduYXR1cmU=" // Base64 encoded "dummysignature" - }))) - .mount(mock_server) - .await; + })).unwrap()) + .create_async() + .await } - async fn setup_mock_sign_error(mock_server: &MockServer) { - Mock::given(method("POST")) - .and(path_regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*:asymmetricSign")) - .and(header_exists("Authorization")) - .respond_with(ResponseTemplate::new(400).set_body_json(json!({ + async fn setup_mock_sign_error(mock_server: &mut ServerGuard) -> Mock { + mock_server + .mock("POST", mockito::Matcher::Regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*:asymmetricSign".to_string())) + .match_header("Authorization", mockito::Matcher::Any) + .with_status(400) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&json!({ "error": { "code": 400, "message": "Invalid request", "status": "INVALID_ARGUMENT" } - }))) - .mount(mock_server) - .await; + })).unwrap()) + .create_async() + .await } - async fn setup_mock_get_key_error(mock_server: &MockServer) { - Mock::given(method("GET")) - .and(path_regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*/publicKey")) - .and(header_exists("Authorization")) - .respond_with(ResponseTemplate::new(404).set_body_json(json!({ + async fn setup_mock_get_key_error(mock_server: &mut ServerGuard) -> Mock { + mock_server + .mock("GET", mockito::Matcher::Regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*/publicKey".to_string())) + .match_header("Authorization", mockito::Matcher::Any) + .with_status(404) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&json!({ "error": { "code": 404, "message": "Key not found", "status": "NOT_FOUND" } - }))) - .mount(mock_server) - .await; + })).unwrap()) + .create_async() + .await } - async fn setup_mock_malformed_response(mock_server: &MockServer) { - Mock::given(method("GET")) - .and(path_regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*/publicKey")) - .and(header_exists("Authorization")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ + async fn setup_mock_malformed_response(mock_server: &mut ServerGuard) -> Mock { + mock_server + .mock("GET", mockito::Matcher::Regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*/publicKey".to_string())) + .match_header("Authorization", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&json!({ "algorithm": "ED25519" // Missing "pem" field - }))) - .mount(mock_server) - .await; + })).unwrap()) + .create_async() + .await } // GoogleCloudKmsServiceTrait tests #[tokio::test] async fn test_get_solana_address_success() { - let mock_server = MockServer::start().await; - setup_mock_solana_public_key(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_solana_public_key(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = service.get_solana_address().await; @@ -589,10 +600,10 @@ mod tests { #[tokio::test] async fn test_get_solana_address_api_error() { - let mock_server = MockServer::start().await; - setup_mock_get_key_error(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_get_key_error(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = service.get_solana_address().await; @@ -605,10 +616,10 @@ mod tests { #[tokio::test] async fn test_get_evm_address_success() { - let mock_server = MockServer::start().await; - setup_mock_evm_public_key(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_evm_public_key(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = GoogleCloudKmsServiceTrait::get_evm_address(&service).await; @@ -621,10 +632,10 @@ mod tests { #[tokio::test] async fn test_sign_solana_success() { - let mock_server = MockServer::start().await; - setup_mock_sign_success(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_sign_success(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = service.sign_solana(b"test message").await; @@ -634,10 +645,10 @@ mod tests { #[tokio::test] async fn test_sign_solana_api_error() { - let mock_server = MockServer::start().await; - setup_mock_sign_error(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_sign_error(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = service.sign_solana(b"test message").await; @@ -650,10 +661,10 @@ mod tests { #[tokio::test] async fn test_sign_evm_success() { - let mock_server = MockServer::start().await; - setup_mock_sign_success(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_sign_success(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = service.sign_evm(b"test message").await; @@ -663,10 +674,10 @@ mod tests { #[tokio::test] async fn test_sign_evm_api_error() { - let mock_server = MockServer::start().await; - setup_mock_sign_error(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_sign_error(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = service.sign_evm(b"test message").await; @@ -680,10 +691,10 @@ mod tests { // GoogleCloudKmsEvmService tests #[tokio::test] async fn test_evm_service_get_address_success() { - let mock_server = MockServer::start().await; - setup_mock_evm_public_key(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_evm_public_key(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = GoogleCloudKmsEvmService::get_evm_address(&service).await; @@ -698,10 +709,10 @@ mod tests { #[tokio::test] async fn test_evm_service_get_address_api_error() { - let mock_server = MockServer::start().await; - setup_mock_get_key_error(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_get_key_error(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = GoogleCloudKmsEvmService::get_evm_address(&service).await; @@ -728,10 +739,10 @@ mod tests { #[tokio::test] async fn test_get_pem_public_key_success() { - let mock_server = MockServer::start().await; - setup_mock_evm_public_key(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_evm_public_key(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = GoogleCloudKmsK256::get_pem_public_key(&service).await; @@ -741,10 +752,10 @@ mod tests { #[tokio::test] async fn test_get_pem_public_key_missing_field() { - let mock_server = MockServer::start().await; - setup_mock_malformed_response(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_malformed_response(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = GoogleCloudKmsK256::get_pem_public_key(&service).await; @@ -757,10 +768,10 @@ mod tests { #[tokio::test] async fn test_sign_digest_success() { - let mock_server = MockServer::start().await; - setup_mock_sign_success(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_sign_success(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let digest = [0u8; 32]; @@ -771,10 +782,10 @@ mod tests { #[tokio::test] async fn test_sign_digest_api_error() { - let mock_server = MockServer::start().await; - setup_mock_sign_error(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_sign_error(&mut mock_server).await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let digest = [0u8; 32]; @@ -845,16 +856,18 @@ mod tests { #[tokio::test] async fn test_malformed_json_response() { - let mock_server = MockServer::start().await; - - Mock::given(method("GET")) - .and(path_regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*/publicKey")) - .and(header_exists("Authorization")) - .respond_with(ResponseTemplate::new(200).set_body_string("invalid json")) - .mount(&mock_server) + let mut mock_server = mockito::Server::new_async().await; + + let _mock = mock_server + .mock("GET", mockito::Matcher::Regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*/publicKey".to_string())) + .match_header("Authorization", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body("invalid json") + .create_async() .await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = service.get_solana_address().await; @@ -867,19 +880,21 @@ mod tests { #[tokio::test] async fn test_missing_signature_field_in_response() { - let mock_server = MockServer::start().await; - - Mock::given(method("POST")) - .and(path_regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*:asymmetricSign")) - .and(header_exists("Authorization")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ + let mut mock_server = mockito::Server::new_async().await; + + let _mock = mock_server + .mock("POST", mockito::Matcher::Regex(r"/v1/projects/.*/locations/global/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*:asymmetricSign".to_string())) + .match_header("Authorization", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&json!({ "name": "test-key" // Missing "signature" field - }))) - .mount(&mock_server) + })).unwrap()) + .create_async() .await; - let config = create_test_config(&mock_server.uri()); + let config = create_test_config(&mock_server.url()); let service = GoogleCloudKmsService::new(&config).unwrap(); let result = service.sign_solana(b"test").await; diff --git a/src/services/jupiter/mod.rs b/src/services/jupiter/mod.rs index b477cd33a..cdbf3694a 100644 --- a/src/services/jupiter/mod.rs +++ b/src/services/jupiter/mod.rs @@ -580,10 +580,7 @@ impl JupiterService { #[cfg(test)] mod tests { use super::*; - use wiremock::{ - matchers::{method, path, query_param}, - Mock, MockServer, ResponseTemplate, - }; + use mockito; #[tokio::test] async fn test_get_quote() { @@ -662,7 +659,7 @@ mod tests { #[tokio::test] async fn test_get_swap_transaction() { - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; let quote = QuoteResponse { input_mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v".to_string(), @@ -698,16 +695,17 @@ mod tests { simulation_error: None, }; - Mock::given(method("POST")) - .and(path("/swap/v1/swap")) - .respond_with(ResponseTemplate::new(200).set_body_json(&swap_response)) - .expect(1) - .mount(&mock_server) + let _mock = mock_server + .mock("POST", "/swap/v1/swap") + .with_status(200) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&swap_response).unwrap()) + .create_async() .await; let service = MainnetJupiterService { client: Client::new(), - base_url: mock_server.uri(), + base_url: mock_server.url(), }; let request = SwapRequest { @@ -731,7 +729,7 @@ mod tests { #[tokio::test] async fn test_get_ultra_order() { - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; let ultra_response = UltraOrderResponse { input_mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v".to_string(), @@ -760,25 +758,28 @@ mod tests { request_id: "test_request_id".to_string(), }; - Mock::given(method("GET")) - .and(path("/ultra/v1/order")) - .and(query_param( - "inputMint", - "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", - )) - .and(query_param( - "outputMint", - "So11111111111111111111111111111111111111112", - )) - .and(query_param("amount", "1000000")) - .and(query_param("taker", "test_taker")) - .respond_with(ResponseTemplate::new(200).set_body_json(&ultra_response)) - .expect(1) - .mount(&mock_server) + let _mock = mock_server + .mock("GET", "/ultra/v1/order") + .match_query(mockito::Matcher::AllOf(vec![ + mockito::Matcher::UrlEncoded( + "inputMint".into(), + "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v".into(), + ), + mockito::Matcher::UrlEncoded( + "outputMint".into(), + "So11111111111111111111111111111111111111112".into(), + ), + mockito::Matcher::UrlEncoded("amount".into(), "1000000".into()), + mockito::Matcher::UrlEncoded("taker".into(), "test_taker".into()), + ])) + .with_status(200) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&ultra_response).unwrap()) + .create_async() .await; let service = MainnetJupiterService { client: Client::new(), - base_url: mock_server.uri(), + base_url: mock_server.url(), }; let request = UltraOrderRequest { @@ -800,7 +801,7 @@ mod tests { #[tokio::test] async fn test_execute_ultra_order() { - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; let execute_response = UltraExecuteResponse { signature: Some("mock_signature".to_string()), @@ -820,16 +821,17 @@ mod tests { }]), }; - Mock::given(method("POST")) - .and(path("/ultra/v1/execute")) - .respond_with(ResponseTemplate::new(200).set_body_json(&execute_response)) - .expect(1) - .mount(&mock_server) + let _mock = mock_server + .mock("POST", "/ultra/v1/execute") + .with_status(200) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&execute_response).unwrap()) + .create_async() .await; let service = MainnetJupiterService { client: Client::new(), - base_url: mock_server.uri(), + base_url: mock_server.url(), }; let request = UltraExecuteRequest { @@ -846,18 +848,21 @@ mod tests { #[tokio::test] async fn test_error_handling_for_api_errors() { - let mock_server = MockServer::start().await; - - Mock::given(method("GET")) - .and(path("/ultra/v1/order")) - .respond_with(ResponseTemplate::new(400).set_body_string("Invalid request")) - .expect(1) - .mount(&mock_server) + let mut mock_server = mockito::Server::new_async().await; + + let _mock = mock_server + .mock( + "GET", + mockito::Matcher::Regex(r"/ultra/v1/order\?.*".to_string()), + ) + .with_status(400) + .with_body("Invalid request") + .create_async() .await; let service = MainnetJupiterService { client: Client::new(), - base_url: mock_server.uri(), + base_url: mock_server.url(), }; let request = UltraOrderRequest { diff --git a/src/services/notification/mod.rs b/src/services/notification/mod.rs index 1bf5bee8c..bcff8ac1f 100644 --- a/src/services/notification/mod.rs +++ b/src/services/notification/mod.rs @@ -133,9 +133,8 @@ mod tests { use crate::models::{WebhookNotification, WebhookPayload}; use crate::services::notification::WebhookNotificationService; use base64::{engine::general_purpose::STANDARD, Engine}; + use mockito; use serde_json::json; - use wiremock::matchers::{header_exists, method, path}; - use wiremock::{Mock, MockServer, ResponseTemplate}; fn mock_transaction_response() -> TransactionResponse { TransactionResponse::Evm(Box::new(EvmTransactionResponse { @@ -163,22 +162,24 @@ mod tests { #[tokio::test] async fn test_successful_notification_with_signature() { - let mock_server = MockServer::start().await; - Mock::given(method("POST")) - .and(path("/")) - .and(header_exists("X-Signature")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ - "status": "success", - "message": null - }))) - .mount(&mock_server) + let mut mock_server = mockito::Server::new_async().await; + let _mock = mock_server + .mock("POST", "/") + .match_header("X-Signature", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "status": "success", + "message": null + })) + .unwrap(), + ) + .create_async() .await; let secret_key = SecretString::new("test_secret"); - let service = WebhookNotificationService::new( - mock_server.uri().to_string(), - Some(secret_key.clone()), - ); + let service = WebhookNotificationService::new(mock_server.url(), Some(secret_key.clone())); let notification = WebhookNotification { id: "123".to_string(), @@ -193,17 +194,22 @@ mod tests { #[tokio::test] async fn test_failed_notification_without_signature() { - let mock_server = MockServer::start().await; - Mock::given(method("POST")) - .and(path("/")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ - "status": "success", - "message": null - }))) - .mount(&mock_server) + let mut mock_server = mockito::Server::new_async().await; + let _mock = mock_server + .mock("POST", "/") + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "status": "success", + "message": null + })) + .unwrap(), + ) + .create_async() .await; - let service = WebhookNotificationService::new(mock_server.uri().to_string(), None); + let service = WebhookNotificationService::new(mock_server.url(), None); let notification = WebhookNotification { id: "123".to_string(), @@ -218,21 +224,23 @@ mod tests { #[tokio::test] async fn test_failed_notification_with_http_error() { - let mock_server = MockServer::start().await; - Mock::given(method("POST")) - .and(path("/")) - .respond_with(ResponseTemplate::new(500).set_body_json(json!({ - "status": "error", - "message": "Internal Server Error" - }))) - .mount(&mock_server) + let mut mock_server = mockito::Server::new_async().await; + let _mock = mock_server + .mock("POST", "/") + .with_status(500) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "status": "error", + "message": "Internal Server Error" + })) + .unwrap(), + ) + .create_async() .await; let secret_key = SecretString::new("test_secret"); - let service = WebhookNotificationService::new( - mock_server.uri().to_string(), - Some(secret_key.clone()), - ); + let service = WebhookNotificationService::new(mock_server.url(), Some(secret_key.clone())); let notification = WebhookNotification { id: "123".to_string(), diff --git a/src/services/provider/mod.rs b/src/services/provider/mod.rs index 474de6eeb..22e6b7a15 100644 --- a/src/services/provider/mod.rs +++ b/src/services/provider/mod.rs @@ -275,11 +275,10 @@ pub fn get_network_provider( mod tests { use super::*; use lazy_static::lazy_static; + use mockito; use std::env; use std::sync::Mutex; use std::time::Duration; - use wiremock::matchers::any; - use wiremock::{Mock, MockServer, ResponseTemplate}; // Use a mutex to ensure tests don't run in parallel when modifying env vars lazy_static! { @@ -380,16 +379,17 @@ mod tests { #[actix_rt::test] async fn test_categorize_reqwest_error_rate_limited() { - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; - Mock::given(any()) - .respond_with(ResponseTemplate::new(429)) - .mount(&mock_server) + let _mock = mock_server + .mock("GET", mockito::Matcher::Any) + .with_status(429) + .create_async() .await; let client = reqwest::Client::new(); let response = client - .get(mock_server.uri()) + .get(mock_server.url()) .send() .await .expect("Failed to get response"); @@ -407,16 +407,17 @@ mod tests { #[actix_rt::test] async fn test_categorize_reqwest_error_bad_gateway() { - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; - Mock::given(any()) - .respond_with(ResponseTemplate::new(502)) - .mount(&mock_server) + let _mock = mock_server + .mock("GET", mockito::Matcher::Any) + .with_status(502) + .create_async() .await; let client = reqwest::Client::new(); let response = client - .get(mock_server.uri()) + .get(mock_server.url()) .send() .await .expect("Failed to get response"); diff --git a/src/services/signer/evm/google_cloud_kms_signer.rs b/src/services/signer/evm/google_cloud_kms_signer.rs index 3ae27d2d9..ffef0f60f 100644 --- a/src/services/signer/evm/google_cloud_kms_signer.rs +++ b/src/services/signer/evm/google_cloud_kms_signer.rs @@ -168,11 +168,10 @@ mod tests { EvmTransactionData, GoogleCloudKmsSignerConfig, GoogleCloudKmsSignerKeyConfig, GoogleCloudKmsSignerServiceAccountConfig, SecretString, U256, }; - use wiremock::matchers::{header_exists, method, path_regex}; - use wiremock::{Mock, MockServer, ResponseTemplate}; + use mockito::{Mock, ServerGuard}; - async fn setup_mock_gcp_signer(mock_server: &MockServer) -> GoogleCloudKmsSigner { - let base_url = mock_server.uri(); + async fn setup_mock_gcp_signer(mock_server: &ServerGuard) -> GoogleCloudKmsSigner { + let base_url = mock_server.url(); let config = GoogleCloudKmsSignerConfig { service_account: GoogleCloudKmsSignerServiceAccountConfig { @@ -201,19 +200,28 @@ mod tests { #[tokio::test] async fn test_address_evm() { - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; // Mock the public key endpoint - Mock::given(method("GET")) - .and(path_regex( - r"/v1/projects/.*/locations/.*/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*", - )) - .and(header_exists("authorization")) - .respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({ - "pem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjJaJh5wfZwvj8b3bQ4GYikqDTLXWUjMh\nkFs9lGj2N9B17zo37p4PSy99rDio0QHLadpso0rtTJDSISRW9MdOqA==\n-----END PUBLIC KEY-----\n", // noboost - "algorithm": "ECDSA_SECP256K1_SHA256" - }))) - .mount(&mock_server) + let _mock = mock_server + .mock( + "GET", + mockito::Matcher::Regex( + r"/v1/projects/.*/locations/.*/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*" + .to_string(), + ), + ) + .match_header("authorization", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&serde_json::json!({ + "pem": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEjJaJh5wfZwvj8b3bQ4GYikqDTLXWUjMh\nkFs9lGj2N9B17zo37p4PSy99rDio0QHLadpso0rtTJDSISRW9MdOqA==\n-----END PUBLIC KEY-----\n", // noboost + "algorithm": "ECDSA_SECP256K1_SHA256" + })) + .unwrap(), + ) + .create_async() .await; let signer = setup_mock_gcp_signer(&mock_server).await; @@ -229,7 +237,7 @@ mod tests { use k256::pkcs8::EncodePublicKey; use sha3::{Digest, Keccak256}; - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; // Generate a test keypair let signing_key = SigningKey::from_slice( @@ -247,16 +255,25 @@ mod tests { ); // Mock the public key endpoint with our generated public key - Mock::given(method("GET")) - .and(path_regex( - r"/v1/projects/.*/locations/.*/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*", - )) - .and(header_exists("authorization")) - .respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({ - "pem": public_key_pem, - "algorithm": "ECDSA_SECP256K1_SHA256" - }))) - .mount(&mock_server) + let _mock_pubkey = mock_server + .mock( + "GET", + mockito::Matcher::Regex( + r"/v1/projects/.*/locations/.*/keyRings/.*/cryptoKeys/.*/cryptoKeyVersions/.*" + .to_string(), + ), + ) + .match_header("authorization", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&serde_json::json!({ + "pem": public_key_pem, + "algorithm": "ECDSA_SECP256K1_SHA256" + })) + .unwrap(), + ) + .create_async() .await; // The test message @@ -273,15 +290,24 @@ mod tests { let signature_base64 = base64_encode(der_signature.as_bytes()); // Mock the sign endpoint with the valid signature - Mock::given(method("POST")) - .and(path_regex( - r"/v1/projects/.*/locations/.*/keyRings/.*/cryptoKeys/.*:asymmetricSign", - )) - .and(header_exists("authorization")) - .respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({ - "signature": signature_base64 - }))) - .mount(&mock_server) + let _mock_sign = mock_server + .mock( + "POST", + mockito::Matcher::Regex( + r"/v1/projects/.*/locations/.*/keyRings/.*/cryptoKeys/.*:asymmetricSign" + .to_string(), + ), + ) + .match_header("authorization", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&serde_json::json!({ + "signature": signature_base64 + })) + .unwrap(), + ) + .create_async() .await; let signer = setup_mock_gcp_signer(&mock_server).await; diff --git a/src/services/turnkey/mod.rs b/src/services/turnkey/mod.rs index 37cec23f2..571a7da45 100644 --- a/src/services/turnkey/mod.rs +++ b/src/services/turnkey/mod.rs @@ -537,9 +537,8 @@ impl TurnkeyServiceTrait for TurnkeyService { #[cfg(test)] mod tests { use super::*; + use mockito; use serde_json::json; - use wiremock::matchers::{header, header_exists, method, path}; - use wiremock::{Mock, MockServer, ResponseTemplate}; fn create_solana_test_config() -> TurnkeySignerConfig { TurnkeySignerConfig { @@ -633,12 +632,14 @@ mod tests { } // Setup mock for signing raw payload - async fn setup_mock_sign_raw_payload(mock_server: &MockServer) { - Mock::given(method("POST")) - .and(path("/public/v1/submit/sign_raw_payload")) - .and(header("Content-Type", "application/json")) - .and(header_exists("X-Stamp")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ + async fn setup_mock_sign_raw_payload(mock_server: &mut mockito::ServerGuard) -> mockito::Mock { + mock_server + .mock("POST", "/public/v1/submit/sign_raw_payload") + .match_header("Content-Type", "application/json") + .match_header("X-Stamp", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body(serde_json::to_string(&json!({ "activity": { "id": "test-activity-id", "status": "ACTIVITY_STATUS_COMPLETE", @@ -650,46 +651,58 @@ mod tests { } } } - }))) - .mount(mock_server) - .await; + })).unwrap()) + .create_async() + .await } // Setup mock for signing EVM transaction - async fn setup_mock_sign_evm_transaction(mock_server: &MockServer) { - Mock::given(method("POST")) - .and(path("/public/v1/submit/sign_transaction")) - .and(header("Content-Type", "application/json")) - .and(header_exists("X-Stamp")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ - "activity": { - "id": "test-activity-id", - "status": "ACTIVITY_STATUS_COMPLETE", - "result": { - "signTransactionResult": { - "signedTransaction": "02f1010203050607080910" // Example signed transaction hex + async fn setup_mock_sign_evm_transaction( + mock_server: &mut mockito::ServerGuard, + ) -> mockito::Mock { + mock_server + .mock("POST", "/public/v1/submit/sign_transaction") + .match_header("Content-Type", "application/json") + .match_header("X-Stamp", mockito::Matcher::Any) + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "activity": { + "id": "test-activity-id", + "status": "ACTIVITY_STATUS_COMPLETE", + "result": { + "signTransactionResult": { + "signedTransaction": "02f1010203050607080910" // Example signed transaction hex + } } } - } - }))) - .mount(mock_server) - .await; + })) + .unwrap(), + ) + .create_async() + .await } // Setup mock for error response - async fn setup_mock_error_response(mock_server: &MockServer) { - Mock::given(method("POST")) - .and(path("/public/v1/submit/sign_raw_payload")) - .and(header("Content-Type", "application/json")) - .and(header_exists("X-Stamp")) - .respond_with(ResponseTemplate::new(400).set_body_json(json!({ - "error": { - "code": 400, - "message": "Invalid payload format" - } - }))) - .mount(mock_server) - .await; + async fn setup_mock_error_response(mock_server: &mut mockito::ServerGuard) -> mockito::Mock { + mock_server + .mock("POST", "/public/v1/submit/sign_raw_payload") + .match_header("Content-Type", "application/json") + .match_header("X-Stamp", mockito::Matcher::Any) + .with_status(400) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "error": { + "code": 400, + "message": "Invalid payload format" + } + })) + .unwrap(), + ) + .create_async() + .await } // Helper function to create a modified client for testing @@ -702,8 +715,8 @@ mod tests { #[tokio::test] async fn test_sign_solana() { - let mock_server = MockServer::start().await; - setup_mock_sign_raw_payload(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_sign_raw_payload(&mut mock_server).await; let config = create_solana_test_config(); @@ -713,7 +726,7 @@ mod tests { organization_id: config.organization_id, private_key_id: config.private_key_id, public_key: config.public_key, - base_url: mock_server.uri(), + base_url: mock_server.url(), client: create_test_client(), }; @@ -725,8 +738,8 @@ mod tests { #[tokio::test] async fn test_sign_evm() { - let mock_server = MockServer::start().await; - setup_mock_sign_raw_payload(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_sign_raw_payload(&mut mock_server).await; let config = create_evm_test_config(); let service = TurnkeyService { @@ -735,7 +748,7 @@ mod tests { organization_id: config.organization_id, private_key_id: config.private_key_id, public_key: config.public_key, - base_url: mock_server.uri(), + base_url: mock_server.url(), client: create_test_client(), }; @@ -747,8 +760,8 @@ mod tests { #[tokio::test] async fn test_sign_evm_transaction() { - let mock_server = MockServer::start().await; - setup_mock_sign_evm_transaction(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_sign_evm_transaction(&mut mock_server).await; let config = create_evm_test_config(); let service = TurnkeyService { @@ -757,7 +770,7 @@ mod tests { organization_id: config.organization_id, private_key_id: config.private_key_id, public_key: config.public_key, - base_url: mock_server.uri(), + base_url: mock_server.url(), client: create_test_client(), }; @@ -772,8 +785,8 @@ mod tests { #[tokio::test] async fn test_error_handling() { - let mock_server = MockServer::start().await; - setup_mock_error_response(&mock_server).await; + let mut mock_server = mockito::Server::new_async().await; + let _mock = setup_mock_error_response(&mut mock_server).await; let config = create_solana_test_config(); let service = TurnkeyService { @@ -782,7 +795,7 @@ mod tests { organization_id: config.organization_id, private_key_id: config.private_key_id, public_key: config.public_key, - base_url: mock_server.uri(), + base_url: mock_server.url(), client: create_test_client(), }; diff --git a/src/services/vault/mod.rs b/src/services/vault/mod.rs index a9cd646e8..4a1eed393 100644 --- a/src/services/vault/mod.rs +++ b/src/services/vault/mod.rs @@ -284,9 +284,8 @@ impl VaultServiceTrait for VaultService { #[cfg(test)] mod tests { use super::*; + use mockito; use serde_json::json; - use wiremock::matchers::{body_json, header, method, path}; - use wiremock::{Mock, MockServer, ResponseTemplate}; #[test] fn test_vault_config_new() { @@ -368,79 +367,94 @@ mod tests { // utility function to setup a mock AppRole login response async fn setup_mock_approle_login( - mock_server: &MockServer, + mock_server: &mut mockito::ServerGuard, role_id: &str, secret_id: &str, token: &str, - ) { - Mock::given(method("POST")) - .and(path("/v1/auth/approle/login")) - .and(body_json(json!({ + ) -> mockito::Mock { + mock_server + .mock("POST", "/v1/auth/approle/login") + .match_body(mockito::Matcher::Json(json!({ "role_id": role_id, "secret_id": secret_id }))) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ - "request_id": "test-request-id", - "lease_id": "", - "renewable": false, - "lease_duration": 0, - "data": null, - "wrap_info": null, - "warnings": null, - "auth": { - "client_token": token, - "accessor": "test-accessor", - "policies": ["default"], - "token_policies": ["default"], - "metadata": { - "role_name": "test-role" - }, - "lease_duration": 3600, - "renewable": true, - "entity_id": "test-entity-id", - "token_type": "service", - "orphan": true - } - }))) - .mount(mock_server) - .await; + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "request_id": "test-request-id", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": null, + "wrap_info": null, + "warnings": null, + "auth": { + "client_token": token, + "accessor": "test-accessor", + "policies": ["default"], + "token_policies": ["default"], + "metadata": { + "role_name": "test-role" + }, + "lease_duration": 3600, + "renewable": true, + "entity_id": "test-entity-id", + "token_type": "service", + "orphan": true + } + })) + .unwrap(), + ) + .create_async() + .await } #[tokio::test] async fn test_vault_service_auth_failure() { - let mock_server = MockServer::start().await; - - setup_mock_approle_login(&mock_server, "test-role-id", "test-secret-id", "test-token") - .await; + let mut mock_server = mockito::Server::new_async().await; - Mock::given(method("GET")) - .and(path("/v1/test-mount/data/my-secret")) - .and(header("X-Vault-Token", "test-token")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ - "request_id": "test-request-id", - "lease_id": "", - "renewable": false, - "lease_duration": 0, - "data": { + let _login_mock = setup_mock_approle_login( + &mut mock_server, + "test-role-id", + "test-secret-id", + "test-token", + ) + .await; + + let _secret_mock = mock_server + .mock("GET", "/v1/test-mount/data/my-secret") + .match_header("X-Vault-Token", "test-token") + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "request_id": "test-request-id", + "lease_id": "", + "renewable": false, + "lease_duration": 0, "data": { - "value": "super-secret-value" + "data": { + "value": "super-secret-value" + }, + "metadata": { + "created_time": "2024-01-01T00:00:00Z", + "deletion_time": "", + "destroyed": false, + "version": 1 + } }, - "metadata": { - "created_time": "2024-01-01T00:00:00Z", - "deletion_time": "", - "destroyed": false, - "version": 1 - } - }, - "wrap_info": null, - "warnings": null, - "auth": null - }))) - .mount(&mock_server) + "wrap_info": null, + "warnings": null, + "auth": null + })) + .unwrap(), + ) + .create_async() .await; let config = VaultConfig::new( - mock_server.uri(), + mock_server.url(), SecretString::new("test-role-id-fake"), SecretString::new("test-secret-id-fake"), None, @@ -462,39 +476,52 @@ mod tests { #[tokio::test] async fn test_vault_service_retrieve_secret_success() { - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; - setup_mock_approle_login(&mock_server, "test-role-id", "test-secret-id", "test-token") - .await; - - Mock::given(method("GET")) - .and(path("/v1/test-mount/data/my-secret")) - .and(header("X-Vault-Token", "test-token")) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ - "request_id": "test-request-id", - "lease_id": "", - "renewable": false, - "lease_duration": 0, - "data": { + let _login_mock = setup_mock_approle_login( + &mut mock_server, + "test-role-id", + "test-secret-id", + "test-token", + ) + .await; + + let _secret_mock = mock_server + .mock( + "GET", + mockito::Matcher::Regex(r"/v1/test-mount/data/my-secret.*".to_string()), + ) + .match_header("X-Vault-Token", "test-token") + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "request_id": "test-request-id", + "lease_id": "", + "renewable": false, + "lease_duration": 0, "data": { - "value": "super-secret-value" + "data": { + "value": "super-secret-value" + }, + "metadata": { + "created_time": "2024-01-01T00:00:00Z", + "deletion_time": "", + "destroyed": false, + "version": 1 + } }, - "metadata": { - "created_time": "2024-01-01T00:00:00Z", - "deletion_time": "", - "destroyed": false, - "version": 1 - } - }, - "wrap_info": null, - "warnings": null, - "auth": null - }))) - .mount(&mock_server) + "wrap_info": null, + "warnings": null, + "auth": null + })) + .unwrap(), + ) + .create_async() .await; let config = VaultConfig::new( - mock_server.uri(), + mock_server.url(), SecretString::new("test-role-id"), SecretString::new("test-secret-id"), None, @@ -511,38 +538,48 @@ mod tests { #[tokio::test] async fn test_vault_service_sign_success() { - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; - setup_mock_approle_login(&mock_server, "test-role-id", "test-secret-id", "test-token") - .await; + let _login_mock = setup_mock_approle_login( + &mut mock_server, + "test-role-id", + "test-secret-id", + "test-token", + ) + .await; let message = b"hello world"; let encoded_message = base64_encode(message); - Mock::given(method("POST")) - .and(path("/v1/test-mount/sign/my-signing-key")) - .and(header("X-Vault-Token", "test-token")) - .and(body_json(json!({ + let _sign_mock = mock_server + .mock("POST", "/v1/test-mount/sign/my-signing-key") + .match_header("X-Vault-Token", "test-token") + .match_body(mockito::Matcher::Json(json!({ "input": encoded_message }))) - .respond_with(ResponseTemplate::new(200).set_body_json(json!({ - "request_id": "test-request-id", - "lease_id": "", - "renewable": false, - "lease_duration": 0, - "data": { - "signature": "vault:v1:fake-signature", - "key_version": 1 - }, - "wrap_info": null, - "warnings": null, - "auth": null - }))) - .mount(&mock_server) + .with_status(200) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "request_id": "test-request-id", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": { + "signature": "vault:v1:fake-signature", + "key_version": 1 + }, + "wrap_info": null, + "warnings": null, + "auth": null + })) + .unwrap(), + ) + .create_async() .await; let config = VaultConfig::new( - mock_server.uri(), + mock_server.url(), SecretString::new("test-role-id"), SecretString::new("test-secret-id"), None, @@ -558,22 +595,35 @@ mod tests { #[tokio::test] async fn test_vault_service_retrieve_secret_failure() { - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; - setup_mock_approle_login(&mock_server, "test-role-id", "test-secret-id", "test-token") - .await; - - Mock::given(method("GET")) - .and(path("/v1/test-mount/data/my-secret")) - .and(header("X-Vault-Token", "test-token")) - .respond_with(ResponseTemplate::new(404).set_body_json(json!({ - "errors": ["secret not found:"] - }))) - .mount(&mock_server) + let _login_mock = setup_mock_approle_login( + &mut mock_server, + "test-role-id", + "test-secret-id", + "test-token", + ) + .await; + + let _secret_mock = mock_server + .mock( + "GET", + mockito::Matcher::Regex(r"/v1/test-mount/data/my-secret.*".to_string()), + ) + .match_header("X-Vault-Token", "test-token") + .with_status(404) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "errors": ["secret not found:"] + })) + .unwrap(), + ) + .create_async() .await; let config = VaultConfig::new( - mock_server.uri(), + mock_server.url(), SecretString::new("test-role-id"), SecretString::new("test-secret-id"), None, @@ -596,28 +646,38 @@ mod tests { #[tokio::test] async fn test_vault_service_sign_failure() { - let mock_server = MockServer::start().await; + let mut mock_server = mockito::Server::new_async().await; - setup_mock_approle_login(&mock_server, "test-role-id", "test-secret-id", "test-token") - .await; + let _login_mock = setup_mock_approle_login( + &mut mock_server, + "test-role-id", + "test-secret-id", + "test-token", + ) + .await; let message = b"hello world"; let encoded_message = base64_encode(message); - Mock::given(method("POST")) - .and(path("/v1/test-mount/sign/my-signing-key")) - .and(header("X-Vault-Token", "test-token")) - .and(body_json(json!({ + let _sign_mock = mock_server + .mock("POST", "/v1/test-mount/sign/my-signing-key") + .match_header("X-Vault-Token", "test-token") + .match_body(mockito::Matcher::Json(json!({ "input": encoded_message }))) - .respond_with(ResponseTemplate::new(400).set_body_json(json!({ - "errors": ["1 error occurred:\n\t* signing key not found"] - }))) - .mount(&mock_server) + .with_status(400) + .with_header("content-type", "application/json") + .with_body( + serde_json::to_string(&json!({ + "errors": ["1 error occurred:\n\t* signing key not found"] + })) + .unwrap(), + ) + .create_async() .await; let config = VaultConfig::new( - mock_server.uri(), + mock_server.url(), SecretString::new("test-role-id"), SecretString::new("test-secret-id"), None, From 303c2a0c0e5a35922be913c91f6bc5f4dce0e71d Mon Sep 17 00:00:00 2001 From: Luis Urrutia Date: Wed, 27 Aug 2025 16:34:53 +0200 Subject: [PATCH 2/3] fix: Codderabbit nits --- src/services/google_cloud_kms/mod.rs | 10 +++++----- src/services/jupiter/mod.rs | 5 ++++- src/services/notification/mod.rs | 4 ++-- src/services/provider/mod.rs | 1 - src/services/signer/evm/google_cloud_kms_signer.rs | 3 +++ src/services/turnkey/mod.rs | 3 +++ 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/services/google_cloud_kms/mod.rs b/src/services/google_cloud_kms/mod.rs index 53a34120e..de112b75c 100644 --- a/src/services/google_cloud_kms/mod.rs +++ b/src/services/google_cloud_kms/mod.rs @@ -325,7 +325,7 @@ impl GoogleCloudKmsServiceTrait for GoogleCloudKmsService { async fn get_solana_address(&self) -> GoogleCloudKmsResult { let pem_str = self.get_pem().await?; - println!("PEM solana: {}", pem_str); + debug!("PEM solana: {}", pem_str); utils::derive_solana_address_from_pem(&pem_str).map_err(GoogleCloudKmsError::from) } @@ -333,7 +333,7 @@ impl GoogleCloudKmsServiceTrait for GoogleCloudKmsService { async fn get_evm_address(&self) -> GoogleCloudKmsResult { let pem_str = self.get_pem().await?; - println!("PEM evm: {}", pem_str); + debug!("PEM evm: {}", pem_str); let address_bytes = utils::derive_ethereum_address_from_pem(&pem_str).map_err(GoogleCloudKmsError::from)?; @@ -360,7 +360,7 @@ impl GoogleCloudKmsServiceTrait for GoogleCloudKmsService { .and_then(|v| v.as_str()) .ok_or_else(|| GoogleCloudKmsError::MissingField("signature".to_string()))?; - println!("KMS asymmetricSign response: {}", resp); + debug!("KMS asymmetricSign response: {}", resp); let signature = base64_decode(signature_b64) .map_err(|e| GoogleCloudKmsError::ParseError(e.to_string()))?; @@ -392,10 +392,10 @@ impl GoogleCloudKmsServiceTrait for GoogleCloudKmsService { .and_then(|v| v.as_str()) .ok_or_else(|| GoogleCloudKmsError::MissingField("signature".to_string()))?; - println!("KMS asymmetricSign response: {}", resp); + debug!("KMS asymmetricSign response: {}", resp); let signature_b64 = base64_decode(signature).map_err(|e| GoogleCloudKmsError::ParseError(e.to_string()))?; - print!("Signature b64 decoded: {:?}", signature_b64); + debug!("Signature b64 decoded: {:?}", signature_b64); Ok(signature_b64) } } diff --git a/src/services/jupiter/mod.rs b/src/services/jupiter/mod.rs index cdbf3694a..de51f97d8 100644 --- a/src/services/jupiter/mod.rs +++ b/src/services/jupiter/mod.rs @@ -700,6 +700,7 @@ mod tests { .with_status(200) .with_header("content-type", "application/json") .with_body(serde_json::to_string(&swap_response).unwrap()) + .expect(1) .create_async() .await; @@ -775,6 +776,7 @@ mod tests { .with_status(200) .with_header("content-type", "application/json") .with_body(serde_json::to_string(&ultra_response).unwrap()) + .expect(1) .create_async() .await; let service = MainnetJupiterService { @@ -826,6 +828,7 @@ mod tests { .with_status(200) .with_header("content-type", "application/json") .with_body(serde_json::to_string(&execute_response).unwrap()) + .expect(1) .create_async() .await; @@ -881,7 +884,7 @@ mod tests { .to_string() .contains("HTTP status client error (400 Bad Request)")); } - _ => panic!("Expected ApiError but got different error type"), + _ => panic!("Expected HttpRequestError but got different error type"), } } } diff --git a/src/services/notification/mod.rs b/src/services/notification/mod.rs index bcff8ac1f..d639ccf2d 100644 --- a/src/services/notification/mod.rs +++ b/src/services/notification/mod.rs @@ -179,7 +179,7 @@ mod tests { .await; let secret_key = SecretString::new("test_secret"); - let service = WebhookNotificationService::new(mock_server.url(), Some(secret_key.clone())); + let service = WebhookNotificationService::new(mock_server.url(), Some(secret_key)); let notification = WebhookNotification { id: "123".to_string(), @@ -240,7 +240,7 @@ mod tests { .await; let secret_key = SecretString::new("test_secret"); - let service = WebhookNotificationService::new(mock_server.url(), Some(secret_key.clone())); + let service = WebhookNotificationService::new(mock_server.url(), Some(secret_key)); let notification = WebhookNotification { id: "123".to_string(), diff --git a/src/services/provider/mod.rs b/src/services/provider/mod.rs index 22e6b7a15..389f1819f 100644 --- a/src/services/provider/mod.rs +++ b/src/services/provider/mod.rs @@ -275,7 +275,6 @@ pub fn get_network_provider( mod tests { use super::*; use lazy_static::lazy_static; - use mockito; use std::env; use std::sync::Mutex; use std::time::Duration; diff --git a/src/services/signer/evm/google_cloud_kms_signer.rs b/src/services/signer/evm/google_cloud_kms_signer.rs index ffef0f60f..3e625927d 100644 --- a/src/services/signer/evm/google_cloud_kms_signer.rs +++ b/src/services/signer/evm/google_cloud_kms_signer.rs @@ -221,6 +221,7 @@ mod tests { })) .unwrap(), ) + .expect(1) .create_async() .await; @@ -273,6 +274,7 @@ mod tests { })) .unwrap(), ) + .expect(1) .create_async() .await; @@ -307,6 +309,7 @@ mod tests { })) .unwrap(), ) + .expect(1) .create_async() .await; diff --git a/src/services/turnkey/mod.rs b/src/services/turnkey/mod.rs index 571a7da45..5eaedfd12 100644 --- a/src/services/turnkey/mod.rs +++ b/src/services/turnkey/mod.rs @@ -652,6 +652,7 @@ mod tests { } } })).unwrap()) + .expect(1) .create_async() .await } @@ -680,6 +681,7 @@ mod tests { })) .unwrap(), ) + .expect(1) .create_async() .await } @@ -701,6 +703,7 @@ mod tests { })) .unwrap(), ) + .expect(1) .create_async() .await } From 217988be6364278c53a9de2c0a41e2cd8a1ad694 Mon Sep 17 00:00:00 2001 From: Luis Urrutia Date: Wed, 27 Aug 2025 16:54:13 +0200 Subject: [PATCH 3/3] chore: Update mockito version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a5166ca08..adb5ab745 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -91,7 +91,7 @@ solana-system-interface = { version = "1.0.0", features = ["bincode"] } [dev-dependencies] cargo-llvm-cov = "0.6" mockall = { version = "0.13" } -mockito = "1.6.1" +mockito = "1.7.0" proptest = "1.6.0" rand = "0.9.0" tempfile = "3.2"