Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Genera automaticamente dei mock utilizzando l'mockallAWS SDK per Rust
AWS SDK for Rust Fornisce diversi approcci per testare il codice con cui interagisce. Servizi AWS Puoi generare automaticamente la maggior parte delle implementazioni fittizie di cui i tuoi test hanno bisogno utilizzando il popolare programma automock from the crate. mockall
Questo esempio verifica un metodo personalizzato chiamato. determine_prefix_file_size() Questo metodo chiama un metodo list_objects() wrapper personalizzato che chiama Amazon S3. Simulandolist_objects(), il determine_prefix_file_size() metodo può essere testato senza contattare effettivamente Amazon S3.
-
In un prompt dei comandi per la directory del tuo progetto, aggiungi la
mockallcassa come dipendenza:$cargo add --dev mockallL'utilizzo dell'
--devopzioneaggiunge la cassa alla [dev-dependencies]sezione del file.Cargo.tomlCome dipendenza di sviluppo, non viene compilato e incluso nel file binario finale utilizzato per il codice di produzione. Questo codice di esempio utilizza anche Amazon Simple Storage Service come esempio Servizio AWS.
$cargo add aws-sdk-s3In questo modo la cassa viene aggiunta alla
[dependencies]sezione delCargo.tomlfile. -
Includi il
automockmodulo dallamockallcassa.Includi anche qualsiasi altra libreria correlata a Servizio AWS quella che stai testando, in questo caso Amazon S3.
use aws_sdk_s3 as s3; #[allow(unused_imports)] use mockall::automock; use s3::operation::list_objects_v2::{ListObjectsV2Error, ListObjectsV2Output}; -
Quindi, aggiungi il codice che determina quale delle due implementazioni della struttura wrapper Amazon S3 dell'applicazione utilizzare.
-
Quella vera scritta per accedere ad Amazon S3 tramite la rete.
-
L'implementazione fittizia generata da.
mockall
In questo esempio, a quella selezionata viene assegnato il nome
S3. La selezione è condizionata in base all'testattributo:#[cfg(test)] pub use MockS3Impl as S3; #[cfg(not(test))] pub use S3Impl as S3; -
-
La
S3Implstruttura è l'implementazione della struttura wrapper di Amazon S3 a cui invia effettivamente le richieste. AWS-
Quando il test è abilitato, questo codice non viene utilizzato perché la richiesta viene inviata al mock e non. AWS L'
dead_codeattributo dice al linter di non segnalare un problema se ilS3Impltipo non viene utilizzato. -
Il condizionale
#[cfg_attr(test, automock)]indica che quando il test è abilitato, l'automockattributo deve essere impostato. Questo dicemockalldi generare un mock aS3Implcui verrà dato un nome.MockS3Impl -
In questo esempio, il
list_objects()metodo è la chiamata che vuoi deridere.automockcreerà automaticamente unexpect_metodo per te.list_objects()
#[allow(dead_code)] pub struct S3Impl { inner: s3::Client, } #[cfg_attr(test, automock)] impl S3Impl { #[allow(dead_code)] pub fn new(inner: s3::Client) -> Self { Self { inner } } #[allow(dead_code)] pub async fn list_objects( &self, bucket: &str, prefix: &str, continuation_token: Option<String>, ) -> Result<ListObjectsV2Output, s3::error::SdkError<ListObjectsV2Error>> { self.inner .list_objects_v2() .bucket(bucket) .prefix(prefix) .set_continuation_token(continuation_token) .send() .await } } -
-
Crea le funzioni di test in un modulo denominato
test.-
Il condizionale
#[cfg(test)]indica chemockalldovrebbe creare il modulo di test se l'testattributo lo ètrue.
#[cfg(test)] mod test { use super::*; use mockall::predicate::eq; #[tokio::test] async fn test_single_page() { let mut mock = MockS3Impl::default(); mock.expect_list_objects() .with(eq("test-bucket"), eq("test-prefix"), eq(None)) .return_once(|_, _, _| { Ok(ListObjectsV2Output::builder() .set_contents(Some(vec![ // Mock content for ListObjectsV2 response s3::types::Object::builder().size(5).build(), s3::types::Object::builder().size(2).build(), ])) .build()) }); // Run the code we want to test with it let size = determine_prefix_file_size(mock, "test-bucket", "test-prefix") .await .unwrap(); // Verify we got the correct total size back assert_eq!(7, size); } #[tokio::test] async fn test_multiple_pages() { // Create the Mock instance with two pages of objects now let mut mock = MockS3Impl::default(); mock.expect_list_objects() .with(eq("test-bucket"), eq("test-prefix"), eq(None)) .return_once(|_, _, _| { Ok(ListObjectsV2Output::builder() .set_contents(Some(vec![ // Mock content for ListObjectsV2 response s3::types::Object::builder().size(5).build(), s3::types::Object::builder().size(2).build(), ])) .set_next_continuation_token(Some("next".to_string())) .build()) }); mock.expect_list_objects() .with( eq("test-bucket"), eq("test-prefix"), eq(Some("next".to_string())), ) .return_once(|_, _, _| { Ok(ListObjectsV2Output::builder() .set_contents(Some(vec![ // Mock content for ListObjectsV2 response s3::types::Object::builder().size(3).build(), s3::types::Object::builder().size(9).build(), ])) .build()) }); // Run the code we want to test with it let size = determine_prefix_file_size(mock, "test-bucket", "test-prefix") .await .unwrap(); assert_eq!(19, size); } }-
Ogni test utilizza
let mut mock = MockS3Impl::default();per creare un'mockistanza diMockS3Impl. -
Utilizza il
expect_list_objects()metodo mock's (che è stato creato automaticamente daautomock) per impostare il risultato previsto per quando illist_objects()metodo viene utilizzato altrove nel codice. -
Dopo aver stabilito le aspettative, le utilizza per testare la funzione
determine_prefix_file_size()chiamando. Il valore restituito viene controllato per confermare che sia corretto, utilizzando un'asserzione.
-
-
La
determine_prefix_file_size()funzione utilizza il wrapper Amazon S3 per ottenere la dimensione del file del prefisso:#[allow(dead_code)] pub async fn determine_prefix_file_size( // Now we take a reference to our trait object instead of the S3 client // s3_list: ListObjectsService, s3_list: S3, bucket: &str, prefix: &str, ) -> Result<usize, s3::Error> { let mut next_token: Option<String> = None; let mut total_size_bytes = 0; loop { let result = s3_list .list_objects(bucket, prefix, next_token.take()) .await?; // Add up the file sizes we got back for object in result.contents() { total_size_bytes += object.size().unwrap_or(0) as usize; } // Handle pagination, and break the loop if there are no more pages next_token = result.next_continuation_token.clone(); if next_token.is_none() { break; } } Ok(total_size_bytes) }
Il tipo S3 viene utilizzato per chiamare le funzioni Wrapped SDK for Rust per supportare entrambe S3Impl le funzioni e per effettuare richieste HTTP. MockS3Impl Il mock generato automaticamente da mockall segnala eventuali errori di test quando il test è abilitato.
È possibile visualizzare il codice completo per questi esempi