mirror of https://github.com/smithy-lang/smithy-rs
113 lines
3.7 KiB
Rust
113 lines
3.7 KiB
Rust
/*
|
|
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
//! Example of mocking a simple wrapper around S3
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
// this is an example of writing tests, see the tests
|
|
}
|
|
|
|
use aws_sdk_s3::operation::get_object::GetObjectError;
|
|
use aws_sdk_s3::Client;
|
|
use std::error::Error;
|
|
|
|
pub struct MyFileRetriever {
|
|
s3_client: Client,
|
|
}
|
|
|
|
impl MyFileRetriever {
|
|
pub async fn get_file(&self, path: &str) -> Result<Option<String>, Box<dyn Error>> {
|
|
let response = match self
|
|
.s3_client
|
|
.get_object()
|
|
.bucket("test-bucket")
|
|
.key(path)
|
|
.send()
|
|
.await
|
|
.map_err(|e| e.into_service_error())
|
|
{
|
|
Ok(response) => response,
|
|
Err(GetObjectError::NoSuchKey(_)) => return Ok(None),
|
|
e @ Err(_) => e?,
|
|
};
|
|
let contents = response.body.collect().await?.to_vec();
|
|
let contents = String::from_utf8(contents)?;
|
|
Ok(Some(contents))
|
|
}
|
|
}
|
|
|
|
// intentionally not cfg(test) so that rustdoc can find this
|
|
mod test {
|
|
use aws_sdk_s3::config::Region;
|
|
use aws_sdk_s3::operation::get_object::{GetObjectError, GetObjectOutput};
|
|
use aws_sdk_s3::types::error::NoSuchKey;
|
|
use aws_sdk_s3::Client;
|
|
use aws_smithy_mocks_experimental::{mock, MockResponseInterceptor};
|
|
use aws_smithy_runtime_api::client::orchestrator::HttpResponse;
|
|
use aws_smithy_runtime_api::http::StatusCode;
|
|
use aws_smithy_types::body::SdkBody;
|
|
use aws_smithy_types::byte_stream::ByteStream;
|
|
|
|
#[allow(dead_code)]
|
|
fn mocked_client(file_contents: impl AsRef<[u8]>) -> Client {
|
|
let file_contents = file_contents.as_ref().to_vec();
|
|
let get_object_happy_path = mock!(Client::get_object)
|
|
.match_requests(|req| {
|
|
req.bucket() == Some("test-bucket") && req.key() == Some("test-key")
|
|
})
|
|
.then_output(move || {
|
|
GetObjectOutput::builder()
|
|
.body(ByteStream::from(file_contents.clone()))
|
|
.build()
|
|
});
|
|
// fallback error
|
|
let get_object_error_path = mock!(Client::get_object)
|
|
.then_error(|| GetObjectError::NoSuchKey(NoSuchKey::builder().build()));
|
|
let hinted_500_error = mock!(Client::get_object)
|
|
.match_requests(|req| req.key() == Some("500"))
|
|
.then_http_response(|| {
|
|
HttpResponse::new(
|
|
StatusCode::try_from(500).unwrap(),
|
|
SdkBody::from("internal server error"),
|
|
)
|
|
});
|
|
let mock_response_interceptor = MockResponseInterceptor::new()
|
|
.with_rule(&get_object_happy_path)
|
|
.with_rule(&hinted_500_error)
|
|
.with_rule(&get_object_error_path);
|
|
Client::from_conf(
|
|
aws_sdk_s3::Config::builder()
|
|
.with_test_defaults()
|
|
.region(Region::from_static("us-east-1"))
|
|
.interceptor(mock_response_interceptor)
|
|
.build(),
|
|
)
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn loads_file() {
|
|
let client = super::MyFileRetriever {
|
|
s3_client: mocked_client(b"12345-abcde"),
|
|
};
|
|
assert_eq!(
|
|
client.get_file("test-key").await.unwrap().as_deref(),
|
|
Some("12345-abcde")
|
|
);
|
|
assert_eq!(client.get_file("different-key").await.unwrap(), None)
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn returns_error_on_invalid_utf8() {
|
|
let client = super::MyFileRetriever {
|
|
s3_client: mocked_client(&vec![0xFF, 0xFE]),
|
|
};
|
|
client
|
|
.get_file("test-key")
|
|
.await
|
|
.expect_err("invalid UTF-8");
|
|
}
|
|
}
|