在动态特征对象上测试迭代器



我有两种类型的AB来实现Fooable特征。我有一个As 数组和一个Bs 数组,并在两个数组上创建一个迭代器,迭代器具有 Item 类型&dyn Fooable。我想编写一个测试来确认迭代器输出正确的对象,如下所示:

struct C {
as_array: [A; 2],
bs_arry: [B; 2],
}
impl C {
fn contents_iter(&self) -> FoosIterator {
FoosIterator {
a_iter: (&self.as_array).into_iter(),
b_iter: (&self.bs_arry).into_iter(),
}
}
}
struct FoosIterator<'a> {
a_iter: <&'a [A; 2] as IntoIterator>::IntoIter,
b_iter: <&'a [B; 2] as IntoIterator>::IntoIter,
}
impl<'a> Iterator for FoosIterator<'a> {
type Item = &'a dyn Fooable;
fn next(&mut self) -> Option<Self::Item> {
match self.a_iter.next() {
Some(upper_slot) => Some(upper_slot),
None => self.b_iter.next().map(|x| x as &dyn Fooable),
}
}
}
trait Fooable: std::fmt::Debug {
fn calculate_num(&self) -> i32;
}
#[derive(PartialEq, Debug)]
struct A {
value: i32,
}
impl Fooable for A {
fn calculate_num(&self) -> i32 {
self.value
}
}
#[derive(PartialEq, Debug)]
struct B {
value_1: i32,
value_2: i32,
}
impl Fooable for B {
fn calculate_num(&self) -> i32 {
self.value_1 * 5 + self.value_2
}
}
#[test]
fn test_contents_iter() {
let c = C {
as_array: [A { value: 3 }, A { value: 5 }],
bs_arry: [
B {
value_1: 3,
value_2: 1,
},
B {
value_1: 5,
value_2: 2,
},
],
};
let mut iter = c.contents_iter();
assert_eq!(
*iter
.next()
.expect("Should have initial element from iterator"),
A { value: 3 }
);
assert_eq!(
*iter
.next()
.expect("Should have second element from iterator"),
A { value: 5 }
);
assert_eq!(
*iter
.next()
.expect("Should have third element from iterator"),
B {
value_1: 3,
value_2: 1
}
);
assert_eq!(
*iter
.next()
.expect("Should have fourth element from iterator"),
B {
value_1: 5,
value_2: 2
}
);
}

问题是&dyn Fooable类型的对象没有实现PartialEq特征,因此无法比较相等性:

error[E0369]: binary operation `==` cannot be applied to type `dyn Fooable`
--> src/lib.rs:73:5
|
73 | /     assert_eq!(
74 | |         *iter
75 | |             .next()
76 | |             .expect("Should have initial element from iterator"),
77 | |         A { value: 3 }
78 | |     );
| |      ^
| |      |
| |______dyn Fooable
|        A
|
= note: an implementation of `std::cmp::PartialEq` might be missing for `dyn Fooable`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

据我了解(例如,从如何测试特征对象之间的相等性?(没有办法为动态类型实现此特征。有没有办法实现像这里这样的目标?我想人们可以公开一些构成Fooable特征中AB类型的对象的数据,并使用它来检查输出的对象是否正确(在我的实际用例中,As 和Bs 比我上面的玩具示例更复杂(。

在没有任何更好的想法的情况下,一种可能的解决方法是对As 和Bs 使用 Debug 特征:测试格式化调试输出的相等性通常等效于As 和Bs 之间的预期相等概念。

/* ... */
assert_eq!(
format!("{:?}", *iter
.next()
.expect("Should have initial element from iterator")),
format("{:?}", A { value: 3 })
);
assert_eq!(
format!("{:?}", *iter
.next()
.expect("Should have second element from iterator")),
format("{:?}", A { value: 5 })
);
assert_eq!(
format!("{:?}", *iter
.next()
.expect("Should have third element from iterator")),
format("{:?}",         
B {
value_1: 3,
value_2: 1
})
);
assert_eq!(
format!("{:?}", *iter
.next()
.expect("Should have third element from iterator")),
format("{:?}",         
B {
value_1: 5,
value_2: 2
})
);

最新更新