Тестирование итератора над объектами динамических признаков - PullRequest
0 голосов
/ 13 октября 2019

У меня есть два типа A и B, которые реализуют черту Fooable. У меня есть массив A с и массив B с, и я создаю итератор для двух массивов, причем итератор имеет тип элемента &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)

Насколько я понимаю (например, из Как проверить на равенство между объектами признаков? ), нет способа реализовать эту черту для динамического типа. Есть ли способ достичь чего-то вроде цели здесь? Я полагаю, что вместо этого можно выставить некоторые данные, составляющие объекты типа A и B в признаке Fooable, и использовать это для проверки правильности выводимых объектов (в моем реальном случае использования A s и B s сложнее, чем в моем примере с игрушкой выше).

1 Ответ

0 голосов
/ 17 октября 2019

В отсутствие каких-либо лучших идей, один из возможных обходных путей - использовать черту Debug для A s и B s: тестирование отформатированных выходных данных отладки на равенство часто эквивалентно предполагаемому понятию равенства междуA с и B с.

/* ... */
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
    })
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...