use std::io::Error;
use serde::de::DeserializeOwned;
use data_alchemist::reader::{InputReader, InputSource};
pub struct JsonReader;
pub struct JsonProperties {}
impl<T> InputReader<T> for JsonReader where T: DeserializeOwned {
type Properties = JsonProperties;
fn read(source: &dyn InputSource, _: Self::Properties) -> Result<T, Error> {
let raw_data = source.get_data()?;
let deserialized: T = serde_json::from_slice(&raw_data)?;
Ok(deserialized)
}
}
#[cfg(test)]
mod test {
use mockall::*;
use mockall::predicate::*;
use serde_json::{json, Value};
use super::*;
mock! {
#[derive(Debug, Copy)]
pub InputSource {}
impl InputSource for InputSource {
fn get_data(&self) -> Result<Vec<u8>, Error>;
}
}
#[test]
fn given_valid_input_successful_deserializes() {
let json_value = json!({"var1": "Alice", "var2": 30, "optional_var": "optional"});
let expected_output: TestStruct = json_value.to_owned().into();
let mut mock_source = MockInputSource::new();
mock_source.expect_get_data()
.times(1)
.returning(move || serde_json::to_vec(&json_value).map_err(|err| err.into()));
let result: Result<TestStruct, Error> = JsonReader::read(&mock_source, JsonProperties {});
assert!(result.is_ok());
assert_eq!(result.unwrap(), expected_output);
}
#[test]
fn given_unrecognized_var_should_fail() {
let json_value = json!({"var1": "Alice", "var2": 30, "urecognized_var": 30, "optional_var": "optional"});
let mut mock_source = MockInputSource::new();
mock_source.expect_get_data()
.times(1)
.returning(move || serde_json::to_vec(&json_value).map_err(|err| err.into()));
let result: Result<TestStruct, Error> = JsonReader::read(&mock_source, JsonProperties {});
println!("{:?}", result.is_err());
}
#[test]
fn given_missing_required_field_should_fail() {
let json_value = json!({"var2": 30, "optional_var": "optional"});
let mut mock_source = MockInputSource::new();
mock_source.expect_get_data()
.times(1)
.returning(move || serde_json::to_vec(&json_value).map_err(|err| err.into()));
let result: Result<TestStruct, Error> = JsonReader::read(&mock_source, JsonProperties {});
assert!(result.is_err());
}
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
struct TestStruct {
var1: String,
var2: u32,
optional_var: Option<String>,
}
impl Into<Value> for TestStruct {
fn into(self) -> Value {
serde_json::to_value(self).unwrap()
}
}
impl From<Value> for TestStruct {
fn from(value: Value) -> Self {
serde_json::from_value(value).unwrap()
}
}
}