Seleccione sus preferencias de cookies

Usamos cookies esenciales y herramientas similares que son necesarias para proporcionar nuestro sitio y nuestros servicios. Usamos cookies de rendimiento para recopilar estadísticas anónimas para que podamos entender cómo los clientes usan nuestro sitio y hacer mejoras. Las cookies esenciales no se pueden desactivar, pero puede hacer clic en “Personalizar” o “Rechazar” para rechazar las cookies de rendimiento.

Si está de acuerdo, AWS y los terceros aprobados también utilizarán cookies para proporcionar características útiles del sitio, recordar sus preferencias y mostrar contenido relevante, incluida publicidad relevante. Para aceptar o rechazar todas las cookies no esenciales, haga clic en “Aceptar” o “Rechazar”. Para elegir opciones más detalladas, haga clic en “Personalizar”.

Pruebas unitarias

Modo de enfoque
Pruebas unitarias - AWS SDK para Rust

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Si bien hay muchas maneras de implementar las pruebas unitarias en su AWS SDK para Rust proyecto, le recomendamos algunas:

  • automockÚsalo desde la mockall caja para crear y ejecutar tus pruebas.

  • Utilice el motor de ejecución de AWS Smithy StaticReplayClientpara crear un cliente HTTP falso que pueda utilizarse en lugar del cliente HTTP estándar que suele utilizar. Servicios de AWS Este cliente devuelve las respuestas HTTP que especifique en lugar de comunicarse con el servicio a través de la red, de modo que las pruebas obtengan datos conocidos con fines de prueba.

Genera simulaciones automáticamente mediante mockall

Puedes generar automáticamente la mayoría de las implementaciones simuladas que tus pruebas necesitan utilizando las populares automock versiones listas para usar. mockall

En este ejemplo se prueba un método personalizado llamado. determine_prefix_file_size() Este método llama a un método list_objects() contenedor personalizado que llama a Amazon S3. A modo de burlalist_objects(), el determine_prefix_file_size() método se puede probar sin contactar realmente con Amazon S3.

  1. En la línea de comandos del directorio de su proyecto, añada la mockall caja como dependencia:

    $ cargo add mockall

    Esto añade la caja a la [dependencies] sección de tu Cargo.toml archivo.

  2. Incluya el automock módulo de la mockall caja.

    Incluya también cualquier otra biblioteca relacionada con la Servicio de AWS que esté probando, en este caso, Amazon S3.

    use aws_sdk_s3 as s3; #[allow(unused_imports)] use mockall::automock; use s3::operation::list_objects_v2::{ListObjectsV2Error, ListObjectsV2Output};
  3. A continuación, añada un código que determine cuál de las dos implementaciones de la estructura contenedora de Amazon S3 de la aplicación debe utilizarse.

    • El verdadero escrito para acceder a Amazon S3 a través de la red.

    • El simulacro de implementación generado pormockall.

    En este ejemplo, se le da el nombre a la seleccionadaS3. La selección es condicional y se basa en el test atributo:

    #[cfg(test)] pub use MockS3Impl as S3; #[cfg(not(test))] pub use S3Impl as S3;
  4. La S3Impl estructura es la implementación de la estructura contenedora de Amazon S3 a la que realmente envía las solicitudes. AWS

    • Cuando las pruebas están habilitadas, este código no se usa porque la solicitud se envía al simulacro y no. AWS El dead_code atributo le dice al linter que no informe de ningún problema si no se utiliza el S3Impl tipo.

    • El condicional #[cfg_attr(test, automock)] indica que cuando las pruebas están habilitadas, se debe establecer el automock atributo. Esto indica mockall que hay que generar un simulacro del S3Impl que se nombraráMockS3Impl.

    • En este ejemplo, el list_objects() método es la llamada que quieres que se simule. automockcreará automáticamente un expect_list_objects() método para ti.

    #[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 } }
  5. Cree las funciones de prueba en un módulo denominadotest.

    • El condicional #[cfg(test)] indica que se mockall debe construir el módulo de prueba si el test atributo lo estrue.

    #[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); } }
    • Cada prueba se utiliza let mut mock = MockS3Impl::default(); para crear una mock instancia deMockS3Impl.

    • Utiliza el expect_list_objects() método del simulacro (que fue creado automáticamente porautomock) para establecer el resultado esperado cuando el list_objects() método se utilice en otra parte del código.

    • Una vez establecidas las expectativas, las utiliza para probar la función mediante una llamadadetermine_prefix_file_size(). El valor devuelto se comprueba mediante una afirmación para confirmar que es correcto.

  6. La determine_prefix_file_size() función usa el contenedor Amazon S3 para obtener el tamaño del archivo de prefijos:

    #[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) }

Este tipo S3 se utiliza para llamar al SDK empaquetado para que las funciones de Rust sean compatibles con ambas funciones S3Impl y MockS3Impl cuando se realizan solicitudes HTTP. El simulacro generado automáticamente por mockall informa de cualquier error en las pruebas cuando las pruebas están habilitadas.

Puede ver el código completo de estos ejemplos en GitHub.

Simule el tráfico HTTP mediante la reproducción estática

La aws-smithy-runtime caja incluye una clase de utilidad de prueba llamada. StaticReplayClient Esta clase de cliente HTTP se puede especificar en lugar del cliente HTTP predeterminado al crear un Servicio de AWS objeto.

Al inicializarStaticReplayClient, se proporciona una lista de pares de solicitudes y respuestas HTTP como ReplayEvent objetos. Mientras se ejecuta la prueba, se graba cada solicitud HTTP y el cliente devuelve como respuesta del cliente HTTP la siguiente respuesta HTTP que se encuentre ReplayEvent en la siguiente posición de la lista de eventos. Esto permite que la prueba se ejecute con datos conocidos y sin conexión de red.

Uso de la reproducción estática

Para usar la reproducción estática, no necesitas usar un contenedor. En su lugar, determine cómo debe ser el tráfico de red real para los datos que utilizará la prueba y proporcione esos datos de tráfico para que los StaticReplayClient utilice cada vez que el SDK emita una solicitud del Servicio de AWS cliente.

nota

Existen varias formas de recopilar el tráfico de red esperado, incluidos muchos analizadores de AWS CLI tráfico de red y herramientas de rastreo de paquetes.

  • Cree una lista de ReplayEvent objetos en la que se especifiquen las solicitudes HTTP esperadas y las respuestas que se les deben devolver.

  • Cree una StaticReplayClient utilizando la lista de transacciones HTTP creada en el paso anterior.

  • Cree un objeto de configuración para el AWS cliente, especificando el StaticReplayClient como Config objetohttp_client.

  • Cree el objeto de Servicio de AWS cliente mediante la configuración creada en el paso anterior.

  • Realice las operaciones que desee probar utilizando el objeto de servicio que está configurado para utilizar elStaticReplayClient. Cada vez que el SDK envía una solicitud de API a AWS, se utiliza la siguiente respuesta de la lista.

    nota

    Siempre se devuelve la siguiente respuesta de la lista, incluso si la solicitud enviada no coincide con la del vector de ReplayEvent objetos.

  • Cuando se hayan realizado todas las solicitudes deseadas, llama a la StaticReplayClient.assert_requests_match() función para comprobar que las solicitudes enviadas por el SDK coinciden con las de la lista de ReplayEvent objetos.

Ejemplo

Veamos las pruebas realizadas con la misma determine_prefix_file_size() función en el ejemplo anterior, pero utilizando la reproducción estática en lugar de la burla.

  1. En una línea de comandos para el directorio de tu proyecto, agrega la aws-smithy-runtimecaja como una dependencia:

    $ cargo add aws-smithy-runtime --features test-util

    Esto añade la caja a la [dependencies] sección de tu Cargo.toml archivo.

  2. En el archivo fuente, incluye los aws_smithy_runtime tipos que necesitarás.

    use aws_smithy_runtime::client::http::test_util::{ReplayEvent, StaticReplayClient}; use aws_smithy_types::body::SdkBody;
  3. La prueba comienza con la creación de las ReplayEvent estructuras que representan cada una de las transacciones HTTP que deberían tener lugar durante la prueba. Cada evento contiene un objeto de solicitud HTTP y un objeto de respuesta HTTP que representan la información con la que normalmente Servicio de AWS responderían. Estos eventos se transfieren a una llamada aStaticReplayClient::new():

    let page_1 = ReplayEvent::new( http::Request::builder() .method("GET") .uri("https://test-bucket.s3.us-east-1.amazonaws.com/?list-type=2&prefix=test-prefix") .body(SdkBody::empty()) .unwrap(), http::Response::builder() .status(200) .body(SdkBody::from(include_str!("./testing/response_multi_1.xml"))) .unwrap(), ); let page_2 = ReplayEvent::new( http::Request::builder() .method("GET") .uri("https://test-bucket.s3.us-east-1.amazonaws.com/?list-type=2&prefix=test-prefix&continuation-token=next") .body(SdkBody::empty()) .unwrap(), http::Response::builder() .status(200) .body(SdkBody::from(include_str!("./testing/response_multi_2.xml"))) .unwrap(), ); let replay_client = StaticReplayClient::new(vec![page_1, page_2]);

    El resultado se almacena enreplay_client. Esto representa un cliente HTTP que luego puede ser utilizado por el SDK de Rust especificándolo en la configuración del cliente.

  4. Para crear el cliente Amazon S3, llame a la from_conf() función de la clase de cliente para crear el cliente mediante un objeto de configuración:

    let client: s3::Client = s3::Client::from_conf( s3::Config::builder() .behavior_version(BehaviorVersion::latest()) .credentials_provider(make_s3_test_credentials()) .region(s3::config::Region::new("us-east-1")) .http_client(replay_client.clone()) .build(), );

    El objeto de configuración se especifica mediante el http_client() método del generador y las credenciales se especifican mediante el credentials_provider() método. Las credenciales se crean mediante una función llamadamake_s3_test_credentials(), que devuelve una estructura de credenciales falsa:

    fn make_s3_test_credentials() -> s3::config::Credentials { s3::config::Credentials::new( "ATESTCLIENT", "astestsecretkey", Some("atestsessiontoken".to_string()), None, "", ) }

    No es necesario que estas credenciales sean válidas porque, en realidad, no se enviarán a AWS.

  5. Ejecute la prueba llamando a la función que necesita probarse. En este ejemplo, el nombre de esa función esdetermine_prefix_file_size(). Su primer parámetro es el objeto de cliente de Amazon S3 que se va a utilizar para sus solicitudes. Por lo tanto, especifique el cliente creado con el StaticReplayClient fin de que las solicitudes sean gestionadas por él en lugar de enviarse a través de la red:

    let size = determine_prefix_file_size(client, "test-bucket", "test-prefix") .await .unwrap(); assert_eq!(19, size); replay_client.assert_requests_match(&[]);

    Cuando finaliza la llamada a, determine_prefix_file_size() se utiliza una afirmación para confirmar que el valor devuelto coincide con el valor esperado. A continuación, se llama a assert_requests_match() la función del StaticReplayClient método. Esta función escanea las solicitudes HTTP grabadas y confirma que todas coinciden con las especificadas en la matriz de ReplayEvent objetos proporcionada al crear el cliente de reproducción.

Puedes ver el código completo de estos ejemplos en GitHub.

PrivacidadTérminos del sitioPreferencias de cookies
© 2025, Amazon Web Services, Inc o sus afiliados. Todos los derechos reservados.