data-alchemist-json 0.1.2

Implementation of data-alchemist for json
Documentation
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() {
        // given
        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()));

        // when
        let result: Result<TestStruct, Error> = JsonReader::read(&mock_source, JsonProperties {});

        // then
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), expected_output);
    }

    #[test]
    fn given_unrecognized_var_should_fail() {
        // given
        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()));

        // when
        let result: Result<TestStruct, Error> = JsonReader::read(&mock_source, JsonProperties {});

        // then
        println!("{:?}", result.is_err());
    }

    #[test]
    fn given_missing_required_field_should_fail() {
        // given
        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()));

        // when
        let result: Result<TestStruct, Error> = JsonReader::read(&mock_source, JsonProperties {});

        // then
        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()
        }
    }
}