Zia*_*man 5 testing rust serde
Serde 派生宏能够通过字段属性控制字段的序列化/反序列化方式#[serde(with = "module")]。应该"module"具有具有正确参数和返回类型的序列化和反序列化函数。
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, PartialEq, Eq)]
pub struct StringPair(String, String);
mod stringpair_serde {
pub fn serialize<S>(sp: &super::StringPair, ser: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
ser.serialize_str(format!("{}:{}", sp.0, sp.1).as_str())
}
pub fn deserialize<'de, D>(d: D) -> Result<super::StringPair, D::Error>
where
D: serde::Deserializer<'de>,
{
d.deserialize_str(Visitor)
}
struct Visitor;
impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = super::StringPair;
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "a pair of strings separated by colon (:)")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(s.split_once(":")
.map(|tup| super::StringPair(tup.0.to_string(), tup.1.to_string()))
.unwrap_or(Default::default()))
}
}
}
#[derive(Serialize, Deserialize)]
struct UsesStringPair {
// Other fields ...
#[serde(with = "stringpair_serde")]
pub stringpair: StringPair,
}
fn main() {
let usp = UsesStringPair {
stringpair: StringPair("foo".to_string(), "bar".to_string()),
};
assert_eq!(
serde_json::json!(&usp).to_string(),
r#"{"stringpair":"foo:bar"}"#
);
let usp: UsesStringPair = serde_json::from_str(r#"{"stringpair":"baz:qux"}"#).unwrap();
assert_eq!(
usp.stringpair,
StringPair("baz".to_string(), "qux".to_string())
)
}
Run Code Online (Sandbox Code Playgroud)
使用简单的断言来测试派生序列化UsesStringPair是微不足道的。但我看过serde_test例子,因为这对我来说也有意义。
但是,我希望能够独立测试这些stringpair_serde::{serialize, deserialize}功能(例如,如果我的板条箱仅提供mycrate::StringPair和mycrate::stringpair_serde,并且UsesStringPair供板条箱用户实现)。
我研究的一种方法是创建一个serde_json::Serializer(使用new, 需要一个io::Write实现,我无法弄清楚如何简单地创建和使用它,但这是一个单独的问题)并使用创建的序列化器调用序列化,然后对结果和以前一样。然而,这并没有测试 的任何/所有实现serde::Serializer,只是测试 中提供的实现serde_json。
我想知道是否有像serde_test示例中那样的方法适用于模块提供的 ser/deser 函数。
其中没有方法serde_test可以直接测试这些功能。虽然在内部serde_test使用它自己的Serializer类型Deserializer,但它不会公开这些类型,因此您不能在测试中直接使用它们。
但是,您可以使用serde_assert板条箱来完成此操作(免责声明:我写的serde_assert)。serde_assert直接公开它Serializer并Deserializer专门用于测试,并且非常适合您的用例:
use serde_assert::{Deserializer, Serializer, Token, Tokens};
#[test]
fn serialize() {
let serializer = Serializer::builder().build();
assert_eq!(
stringpair_serde::serialize(
&StringPair("foo".to_string(), "bar".to_string()),
&serializer
),
Ok(Tokens(vec![Token::Str("foo:bar".to_string())])),
);
}
#[test]
fn deserialize() {
let mut deserializer = Deserializer::builder()
.tokens(Tokens(vec![Token::Str("foo:bar".to_string())]))
.build();
assert_eq!(
stringpair_serde::deserialize(&mut deserializer),
Ok(StringPair("foo".to_string(), "bar".to_string()))
);
}
Run Code Online (Sandbox Code Playgroud)