Skip to content

Commit 5ee8edf

Browse files
committed
Add Unit tests for VssAccessor
1 parent 0031a6b commit 5ee8edf

File tree

2 files changed

+259
-3
lines changed

2 files changed

+259
-3
lines changed

Cargo.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ edition = "2021"
55
build = "build.rs"
66

77
[dependencies]
8-
prost = "0.11.9"
8+
prost = "0.11.6"
99
reqwest = { version = "0.11.13", features = ["rustls-tls"] }
1010

11-
[dev-dependencies]
12-
1311
[build-dependencies]
1412
prost-build = { version = "0.11.3" }
1513
reqwest = { version = "0.11.13", features = ["blocking"] }
1614

15+
[dev-dependencies]
16+
mockito = "0.31.1"
17+
tokio = { version = "1.22.0", features = ["full"]}
18+
1719
[features]
1820
genproto = []

tests/tests.rs

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
#[cfg(test)]
2+
mod tests {
3+
use mockito::{self, Matcher};
4+
use prost::Message;
5+
use std::future::Future;
6+
use vss_client::client::VssClient;
7+
use vss_client::error::VssError;
8+
9+
use vss_client::types::{
10+
ErrorCode, ErrorResponse, GetObjectRequest, GetObjectResponse, KeyValue, ListKeyVersionsRequest,
11+
ListKeyVersionsResponse, PutObjectRequest, PutObjectResponse,
12+
};
13+
14+
const GET_OBJECT_ENDPOINT: &'static str = "/getObject";
15+
const PUT_OBJECT_ENDPOINT: &'static str = "/putObjects";
16+
const LIST_KEY_VERSIONS_ENDPOINT: &'static str = "/listKeyVersions";
17+
18+
#[tokio::test]
19+
async fn test_get() {
20+
// Spin-up mock server with mock response for given request.
21+
let base_url = mockito::server_url().to_string();
22+
23+
// Set up the mock request/response.
24+
let get_request = build_get_request();
25+
let mut mock_response = GetObjectResponse::default();
26+
mock_response.value = Some(KeyValue { key: "k1".to_string(), version: 2, value: b"k1v2".to_vec() });
27+
28+
// Register the mock endpoint with the mockito server.
29+
let mock_server = mockito::mock("POST", GET_OBJECT_ENDPOINT)
30+
.match_body(get_request.encode_to_vec())
31+
.with_status(200)
32+
.with_body(mock_response.encode_to_vec())
33+
.create();
34+
35+
// Create a new VssClient with the mock server URL.
36+
let vss_acc = VssClient::new(&base_url);
37+
38+
let actual_result = vss_acc.get_object(&get_request).await.unwrap();
39+
40+
let expected_result = &mock_response;
41+
assert_eq!(&actual_result, expected_result);
42+
43+
// Verify server endpoint was called exactly once.
44+
mock_server.expect(1).assert();
45+
}
46+
47+
#[tokio::test]
48+
async fn test_put() {
49+
// Spin-up mock server with mock response for given request.
50+
let base_url = mockito::server_url().to_string();
51+
52+
// Set up the mock request/response.
53+
let request = build_put_request();
54+
let mock_response = PutObjectResponse::default();
55+
56+
// Register the mock endpoint with the mockito server.
57+
let mock_server = mockito::mock("POST", PUT_OBJECT_ENDPOINT)
58+
.match_body(request.encode_to_vec())
59+
.with_status(200)
60+
.with_body(mock_response.encode_to_vec())
61+
.create();
62+
63+
// Create a new VssClient with the mock server URL.
64+
let vss_client = VssClient::new(&base_url);
65+
let actual_result = vss_client.put_object(&request).await.unwrap();
66+
67+
let expected_result = &mock_response;
68+
assert_eq!(&actual_result, expected_result);
69+
70+
// Verify server endpoint was called exactly once.
71+
mock_server.expect(1).assert();
72+
}
73+
74+
#[tokio::test]
75+
async fn test_list_key_versions() {
76+
// Spin-up mock server with mock response for given request.
77+
let base_url = mockito::server_url().to_string();
78+
79+
// Set up the mock request/response.
80+
let request = build_list_request();
81+
let key_versions = vec![
82+
KeyValue { key: "k1".to_string(), version: 3, value: b"".to_vec() },
83+
KeyValue { key: "k2".to_string(), version: 1, value: b"".to_vec() },
84+
];
85+
86+
let mock_response =
87+
ListKeyVersionsResponse { key_versions, global_version: Some(4), next_page_token: Some("k2".into()) };
88+
89+
// Register the mock endpoint with the mockito server.
90+
let mock_server = mockito::mock("POST", LIST_KEY_VERSIONS_ENDPOINT)
91+
.match_body(request.encode_to_vec())
92+
.with_status(200)
93+
.with_body(mock_response.encode_to_vec())
94+
.create();
95+
96+
// Create a new VssClient with the mock server URL.
97+
let vss_acc = VssClient::new(&base_url);
98+
99+
let actual_result = vss_acc.list_key_versions(&request).await.unwrap();
100+
101+
let expected_result = &mock_response;
102+
assert_eq!(&actual_result, expected_result);
103+
104+
// Verify server endpoint was called exactly once.
105+
mock_server.expect(1).assert();
106+
}
107+
108+
#[tokio::test]
109+
async fn test_invalid_request_err_handling() {
110+
let base_url = mockito::server_url();
111+
let vss_client = VssClient::new(&base_url);
112+
113+
// Invalid Request Error
114+
let error_response = ErrorResponse {
115+
error_code: ErrorCode::InvalidRequestException.into(),
116+
message: "InvalidRequestException".to_string(),
117+
};
118+
let mock_server = mockito::mock("POST", Matcher::Any)
119+
.with_status(400)
120+
.with_body(&error_response.encode_to_vec())
121+
.create();
122+
123+
let get_result = vss_client.get_object(&build_get_request()).await;
124+
assert!(matches!(get_result.unwrap_err(), VssError::InvalidRequestError { .. }));
125+
126+
let put_result = vss_client.put_object(&build_put_request()).await;
127+
assert!(matches!(put_result.unwrap_err(), VssError::InvalidRequestError { .. }));
128+
129+
let list_result = vss_client.list_key_versions(&build_list_request()).await;
130+
assert!(matches!(list_result.unwrap_err(), VssError::InvalidRequestError { .. }));
131+
132+
// Verify 3 requests hit the server
133+
mock_server.expect(3).assert();
134+
}
135+
136+
#[tokio::test]
137+
async fn test_conflict_err_handling() {
138+
let base_url = mockito::server_url();
139+
let vss_client = VssClient::new(&base_url);
140+
141+
// Conflict Error
142+
let error_response =
143+
ErrorResponse { error_code: ErrorCode::ConflictException.into(), message: "ConflictException".to_string() };
144+
let mock_server = mockito::mock("POST", Matcher::Any)
145+
.with_status(409)
146+
.with_body(&error_response.encode_to_vec())
147+
.create();
148+
149+
let put_result = vss_client.put_object(&build_put_request()).await;
150+
assert!(matches!(put_result.unwrap_err(), VssError::ConflictError { .. }));
151+
152+
// Verify 1 requests hit the server
153+
mock_server.expect(1).assert();
154+
}
155+
156+
#[tokio::test]
157+
async fn test_internal_server_err_handling() {
158+
let base_url = mockito::server_url();
159+
let vss_client = VssClient::new(&base_url);
160+
161+
// Internal Server Error
162+
let error_response = ErrorResponse {
163+
error_code: ErrorCode::InternalServerException.into(),
164+
message: "InternalServerException".to_string(),
165+
};
166+
let mock_server = mockito::mock("POST", Matcher::Any)
167+
.with_status(500)
168+
.with_body(&error_response.encode_to_vec())
169+
.create();
170+
171+
let get_result = vss_client.get_object(&build_get_request()).await;
172+
assert!(matches!(get_result.unwrap_err(), VssError::InternalServerError { .. }));
173+
174+
let put_result = vss_client.put_object(&build_put_request()).await;
175+
assert!(matches!(put_result.unwrap_err(), VssError::InternalServerError { .. }));
176+
177+
let list_result = vss_client.list_key_versions(&build_list_request()).await;
178+
assert!(matches!(list_result.unwrap_err(), VssError::InternalServerError { .. }));
179+
180+
// Verify 3 requests hit the server
181+
mock_server.expect(3).assert();
182+
}
183+
184+
#[tokio::test]
185+
async fn test_internal_err_handling() {
186+
let base_url = mockito::server_url();
187+
let vss_client = VssClient::new(&base_url);
188+
189+
let error_response = ErrorResponse { error_code: 999, message: "UnknownException".to_string() };
190+
let mut _mock_server = mockito::mock("POST", Matcher::Any)
191+
.with_status(999)
192+
.with_body(&error_response.encode_to_vec())
193+
.create();
194+
195+
let get_request = build_get_request();
196+
let get_result = vss_client.get_object(&get_request).await;
197+
assert!(matches!(get_result.unwrap_err(), VssError::InternalError { .. }));
198+
199+
let put_request = build_put_request();
200+
let put_result = vss_client.put_object(&put_request).await;
201+
assert!(matches!(put_result.unwrap_err(), VssError::InternalError { .. }));
202+
203+
let list_request = build_list_request();
204+
let list_result = vss_client.list_key_versions(&list_request).await;
205+
assert!(matches!(list_result.unwrap_err(), VssError::InternalError { .. }));
206+
207+
let malformed_error_response = b"malformed";
208+
_mock_server = mockito::mock("POST", Matcher::Any)
209+
.with_status(409)
210+
.with_body(&malformed_error_response)
211+
.create();
212+
213+
let get_malformed_err_response = vss_client.get_object(&get_request).await;
214+
assert!(matches!(get_malformed_err_response.unwrap_err(), VssError::InternalError { .. }));
215+
216+
let put_malformed_err_response = vss_client.put_object(&put_request).await;
217+
assert!(matches!(put_malformed_err_response.unwrap_err(), VssError::InternalError { .. }));
218+
219+
let list_malformed_err_response = vss_client.list_key_versions(&list_request).await;
220+
assert!(matches!(list_malformed_err_response.unwrap_err(), VssError::InternalError { .. }));
221+
222+
// Requests to endpoints are no longer mocked and will result in network error.
223+
drop(_mock_server);
224+
225+
let get_network_err = vss_client.get_object(&get_request).await;
226+
assert!(matches!(get_network_err.unwrap_err(), VssError::InternalError { .. }));
227+
228+
let put_network_err = vss_client.put_object(&put_request).await;
229+
assert!(matches!(put_network_err.unwrap_err(), VssError::InternalError { .. }));
230+
231+
let list_network_err = vss_client.list_key_versions(&list_request).await;
232+
assert!(matches!(list_network_err.unwrap_err(), VssError::InternalError { .. }));
233+
}
234+
235+
fn build_get_request() -> GetObjectRequest {
236+
GetObjectRequest { store_id: "store".to_string(), key: "k1".to_string() }
237+
}
238+
239+
fn build_put_request() -> PutObjectRequest {
240+
PutObjectRequest {
241+
store_id: "store".to_string(),
242+
global_version: Some(4),
243+
transaction_items: vec![KeyValue { key: "k1".to_string(), version: 2, value: b"k1v3".to_vec() }],
244+
}
245+
}
246+
fn build_list_request() -> ListKeyVersionsRequest {
247+
ListKeyVersionsRequest {
248+
store_id: "store".to_string(),
249+
page_size: Some(5),
250+
page_token: None,
251+
key_prefix: Some("k".into()),
252+
}
253+
}
254+
}

0 commit comments

Comments
 (0)