Я пытаюсь реализовать пользовательскую функцию/метод десериализации, который использует некоторые внешние функции. Функция создает экземпляр и использует его методы. Он работает нормально, но я не могу понять, как издеваться над сервисом в тестах.
Более общий вопрос: как предоставить состояние функции/методу десериализации?
Код ниже иллюстрирует то, что я имею в виду.
MagickBook
— это внешняя служба, которая хранит состояние и содержит некоторую важную логику в методе MagickBook::find
.
Scroll
— это десериализуемая структура данных, которую следует десериализовать, используя логику из MagicBook
.
Я хотел бы иметь способ предоставить конкретный экземпляр MagicBook
извне в момент десериализации. Например в тестах.
use serde::de::{Deserialize, Deserializer}; // 1.0.82
use serde_derive::Deserialize; // 1.0.82
use serde_json; // 1.0.33
struct MagickBook;
// Some service which I want to mock in the test
impl MagickBook {
fn new() -> Self {
Self {}
}
fn find(&self, _kind: &str) -> isize {
let effect = 42;
// Here we do some logic depending on input parameter
// -- snip --
return effect;
}
}
#[derive(Deserialize, PartialEq, Debug)]
struct Scroll {
#[serde(rename = "kind")]
#[serde(deserialize_with = "deserialize_effect")]
effect: isize,
}
fn deserialize_effect<'de, D>(deserializer: D) -> Result<isize, D::Error>
where
D: Deserializer<'de>,
{
let book = MagickBook::new();
Ok(book.find(&String::deserialize(deserializer)?))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn main() {
let scroll: Scroll = serde_json::from_str("{\"kind\":\"wind\"}").unwrap();
assert_eq!(scroll, Scroll { effect: 42 });
}
}