Я пытаюсь реализовать пользовательскую функцию / метод десериализации, которая использует некоторые внешние функции. Функция создает экземпляр и использует его методы. Он работает нормально, но я не могу понять, как смоделировать сервис в тестах.
Более общий вопрос: как предоставить состояние функции / методу десериализации?
Код ниже иллюстрирует, что я имею в виду.
MagickBook
- это внешний сервис, который содержит состояние и содержит некоторую необходимую логику в методе MagickBook::find
.
Scroll
- десериализуемая структура данных, которая должна быть десериализована с использованием логики MagicBook
.
Мне бы хотелось иметь возможность предоставить конкретный экземпляр MagicBook
извне, в момент десериализации. Например в тестах.
Rust Playground
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 });
}
}