Skip to content

Commit d968479

Browse files
committed
unit-test keret service logic
1 parent ce3919d commit d968479

File tree

5 files changed

+253
-1
lines changed

5 files changed

+253
-1
lines changed

Cargo.lock

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/keret-service-transmit/src/lib.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,21 @@ use chrono::{DateTime, Utc};
22
use serde::{Deserialize, Serialize};
33
use std::time::Duration;
44

5-
#[derive(Debug, Serialize, Deserialize)]
5+
#[derive(Debug, Serialize, Deserialize, PartialEq)]
66
pub struct ActionReport {
77
timestamp: DateTime<Utc>,
88
duration: Duration,
99
}
1010

11+
impl ActionReport {
12+
pub fn new(timestamp: DateTime<Utc>, duration: Duration) -> Self {
13+
Self {
14+
timestamp,
15+
duration,
16+
}
17+
}
18+
}
19+
1120
impl From<u64> for ActionReport {
1221
fn from(value: u64) -> Self {
1322
Self {

src/keret-service/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
1515
snafu = { version = "0.8.4" }
1616
prometheus = { version = "0.13.4", features = ["process"] }
1717
lazy_static = "1.5.0"
18+
mockall = "0.13.0"
19+
chrono = { version = "0.4.38" }
1820
keret-service-transmit = { path = "../keret-service-transmit" }

src/keret-service/src/repository/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub enum RepositoryError {
2828
},
2929
#[snafu(display("Lock is poisoned, can't acquire"))]
3030
LockPoisoned { backtrace: Option<Backtrace> },
31+
#[cfg(test)]
32+
#[snafu(display("Test Error"))]
33+
ErrorOnTest,
3134
}
3235

3336
pub(crate) trait RepositoryStorage {

src/keret-service/src/repository/storage_based_repo.rs

+236
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,239 @@ impl ToDoRepository for StorageBasedRepository {
4444
Ok(new_index)
4545
}
4646
}
47+
48+
#[cfg(test)]
49+
mod test {
50+
use super::*;
51+
use crate::repository::*;
52+
use chrono::{DateTime, Utc};
53+
use mockall::mock;
54+
use mockall::predicate::eq;
55+
use std::time::Duration;
56+
57+
mock! {
58+
MyRepositoryStorage {}
59+
60+
impl RepositoryStorage for MyRepositoryStorage {
61+
fn list(&self) -> Result<Vec<ActionReport>, RepositoryError>;
62+
fn store(&mut self, list: Vec<ActionReport>) -> Result<(), RepositoryError>;
63+
}
64+
}
65+
66+
#[test]
67+
fn list_with_empty_storage_returns_empty_vec() {
68+
// arrange
69+
let mut storage = MockMyRepositoryStorage::default();
70+
storage.expect_list().once().returning(|| Ok(vec![]));
71+
let repo = StorageBasedRepository::new(storage);
72+
73+
// act
74+
let actual = repo.list();
75+
76+
// assert
77+
assert!(actual.is_ok());
78+
assert_eq!(actual.unwrap(), vec![]);
79+
}
80+
81+
#[test]
82+
fn list_with_filled_storage_returns_all_elements() {
83+
// arrange
84+
let mut storage = MockMyRepositoryStorage::default();
85+
storage.expect_list().once().returning(|| {
86+
Ok(vec![
87+
ActionReport::new(
88+
DateTime::<Utc>::from_timestamp(10, 0).unwrap(),
89+
Duration::new(1, 0),
90+
),
91+
ActionReport::new(
92+
DateTime::<Utc>::from_timestamp(20, 0).unwrap(),
93+
Duration::new(1, 0),
94+
),
95+
ActionReport::new(
96+
DateTime::<Utc>::from_timestamp(30, 0).unwrap(),
97+
Duration::new(1, 0),
98+
),
99+
])
100+
});
101+
let repo = StorageBasedRepository::new(storage);
102+
103+
// act
104+
let actual = repo.list();
105+
106+
// assert
107+
assert!(actual.is_ok());
108+
assert_eq!(
109+
actual.unwrap(),
110+
vec![
111+
ActionReport::new(
112+
DateTime::<Utc>::from_timestamp(10, 0).unwrap(),
113+
Duration::new(1, 0)
114+
),
115+
ActionReport::new(
116+
DateTime::<Utc>::from_timestamp(20, 0).unwrap(),
117+
Duration::new(1, 0)
118+
),
119+
ActionReport::new(
120+
DateTime::<Utc>::from_timestamp(30, 0).unwrap(),
121+
Duration::new(1, 0)
122+
),
123+
]
124+
);
125+
}
126+
127+
#[test]
128+
fn list_failing_read_from_storage_returns_error() {
129+
// arrange
130+
let mut storage = MockMyRepositoryStorage::default();
131+
storage
132+
.expect_list()
133+
.once()
134+
.returning(|| ErrorOnTestSnafu.fail());
135+
let repo = StorageBasedRepository::new(storage);
136+
137+
// act
138+
let actual = repo.list();
139+
140+
// assert
141+
assert!(matches!(actual, Err(RepositoryError::ErrorOnTest)));
142+
}
143+
144+
#[test]
145+
fn add_on_empty_storage_writes_one_element() {
146+
// arrange
147+
let mut storage = MockMyRepositoryStorage::default();
148+
storage.expect_list().once().returning(|| Ok(vec![]));
149+
storage
150+
.expect_store()
151+
.once()
152+
.with(eq(vec![ActionReport::new(
153+
DateTime::<Utc>::from_timestamp(10, 0).unwrap(),
154+
Duration::new(1, 0),
155+
)]))
156+
.returning(|_| Ok(()));
157+
let repo = StorageBasedRepository::new(storage);
158+
159+
// act
160+
let actual = repo.add(ActionReport::new(
161+
DateTime::<Utc>::from_timestamp(10, 0).unwrap(),
162+
Duration::new(1, 0),
163+
));
164+
165+
// assert -> mockall
166+
assert!(actual.is_ok());
167+
assert_eq!(actual.unwrap(), 0);
168+
}
169+
170+
#[test]
171+
fn add_on_filled_storage_writes_all_plus_one_elements() {
172+
// arrange
173+
let mut storage = MockMyRepositoryStorage::default();
174+
storage.expect_list().once().returning(|| {
175+
Ok(vec![
176+
ActionReport::new(
177+
DateTime::<Utc>::from_timestamp(10, 0).unwrap(),
178+
Duration::new(1, 0),
179+
),
180+
ActionReport::new(
181+
DateTime::<Utc>::from_timestamp(20, 0).unwrap(),
182+
Duration::new(1, 0),
183+
),
184+
])
185+
});
186+
storage
187+
.expect_store()
188+
.once()
189+
.with(eq(vec![
190+
ActionReport::new(
191+
DateTime::<Utc>::from_timestamp(10, 0).unwrap(),
192+
Duration::new(1, 0),
193+
),
194+
ActionReport::new(
195+
DateTime::<Utc>::from_timestamp(20, 0).unwrap(),
196+
Duration::new(1, 0),
197+
),
198+
ActionReport::new(
199+
DateTime::<Utc>::from_timestamp(90, 0).unwrap(),
200+
Duration::new(1, 0),
201+
),
202+
]))
203+
.returning(|_| Ok(()));
204+
let repo = StorageBasedRepository::new(storage);
205+
206+
// act
207+
let actual = repo.add(ActionReport::new(
208+
DateTime::<Utc>::from_timestamp(90, 0).unwrap(),
209+
Duration::new(1, 0),
210+
));
211+
212+
// assert -> mockall
213+
assert!(actual.is_ok());
214+
assert_eq!(actual.unwrap(), 2);
215+
}
216+
217+
#[test]
218+
fn add_failing_read_from_storage_does_not_store() {
219+
// arrange
220+
let mut storage = MockMyRepositoryStorage::default();
221+
storage
222+
.expect_list()
223+
.once()
224+
.returning(|| ErrorOnTestSnafu.fail());
225+
storage.expect_store().never().returning(|_| Ok(()));
226+
let repo = StorageBasedRepository::new(storage);
227+
228+
// act
229+
let _ = repo.add(ActionReport::new(
230+
DateTime::<Utc>::from_timestamp(90, 0).unwrap(),
231+
Duration::new(1, 0),
232+
));
233+
234+
// assert -> mockall
235+
}
236+
237+
#[test]
238+
fn add_failing_read_from_storage_returns_error() {
239+
// arrange
240+
let mut storage = MockMyRepositoryStorage::default();
241+
storage
242+
.expect_list()
243+
.once()
244+
.returning(|| ErrorOnTestSnafu.fail());
245+
storage.expect_store().never().returning(|_| Ok(()));
246+
let repo = StorageBasedRepository::new(storage);
247+
248+
// act
249+
let actual = repo.add(ActionReport::new(
250+
DateTime::<Utc>::from_timestamp(90, 0).unwrap(),
251+
Duration::new(1, 0),
252+
));
253+
254+
// assert
255+
assert!(matches!(actual, Err(RepositoryError::ErrorOnTest)));
256+
}
257+
258+
#[test]
259+
fn add_failing_store_in_storage_returns_error() {
260+
// arrange
261+
let mut storage = MockMyRepositoryStorage::default();
262+
storage.expect_list().once().returning(|| Ok(vec![]));
263+
storage
264+
.expect_store()
265+
.once()
266+
.with(eq(vec![ActionReport::new(
267+
DateTime::<Utc>::from_timestamp(90, 0).unwrap(),
268+
Duration::new(1, 0),
269+
)]))
270+
.returning(|_| ErrorOnTestSnafu.fail());
271+
let repo = StorageBasedRepository::new(storage);
272+
273+
// act
274+
let actual = repo.add(ActionReport::new(
275+
DateTime::<Utc>::from_timestamp(90, 0).unwrap(),
276+
Duration::new(1, 0),
277+
));
278+
279+
// assert
280+
assert!(matches!(actual, Err(RepositoryError::ErrorOnTest)));
281+
}
282+
}

0 commit comments

Comments
 (0)