unit-testing - 当 `Result`不是 `Copy`时,设计单元测试

标签 unit-testing design-patterns data-structures rust traits

我正在针对要实现的容器类型进行单元测试:

#[test]
fn test_get_mut_normal_tail() -> Result<(), ListError> {
    let mut actual_list: ArrayList<u64> = ArrayList::new();
    let expected_list: ArrayList<u64> = ArrayList {
        elems: vec![1, 2, 3, 8],
    };

    actual_list.append(1)?;
    actual_list.append(2)?;
    actual_list.append(3)?;
    actual_list.append(4)?;

    let actual_res: Result<&mut u64, ListError> = actual_list.get_mut(3);
    let expected_res: Result<&mut u64, ListError> = Ok(&mut 4);

    let elem = actual_res.unwrap();
    *elem *= 2;

    assert_eq!(actual_list, expected_list);
    assert_eq!(actual_res, expected_res);

    Ok(())
}

但是,rustc提示:
error[E0382]: borrow of moved value: `actual_res`
   --> src\arraylist.rs:358:9
    |
351 |         let actual_res: Result<&mut u64, ListError> = actual_list.get_mut(3);
    |             ---------- move occurs because `actual_res` has type `std::result::Result<&mut u64, list::ListError>`, which does not implement the `Copy` trait
...
354 |         let elem = actual_res.unwrap();
    |                    ---------- value moved here
...
358 |         assert_eq!(actual_res, expected_res);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)


我不明白,因为the Result docs表示Result实现Copy(只要所包含的两种类型也都可以)。显然&mut u64实现了Copy,而我的ListError类型derive也实现了它:

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ListError {
    OutOfBounds,
    Impossible,
}
ArrayList::get_mut()的代码在此处(如果相关):

fn get_mut(&mut self, pos: usize) -> Result<&mut T, ListError> {
    if pos >= self.elems.len() { /* bounds check */
        return Err(ListError::OutOfBounds);
    }

    match self.elems.get_mut(pos) {
        Some(elem) => Ok(elem),
        None => Err(ListError::OutOfBounds)
    }
}

总而言之,我有两个问题:
  • 如何解决此错误?
  • 我的测试或实现中是否存在基础问题?
  • 最佳答案

    &mut u64实际上并未实现复制。 &mut T无法实现复制,以防止同时创建多个可变借位。

    引用文档:https://doc.rust-lang.org/std/primitive.reference.html#trait-implementations

    在1的答案中,您可以通过使用assert_eq!(elem, 4);而不是assert_eq!(actual_res, expected_res);来纠正错误。或者,您可以使用Result::map修改并返回新结果

    let actual_res: Result<&mut u64, ListError> = actual_list.get_mut(3).map(|elem| {
      *elem *= 2;
      elem
    };
    

    关于unit-testing - 当 `Result`不是 `Copy`时,设计单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59832570/

    相关文章:

    c# - 数据访问层——模块化和可重用性

    c - 我的 QuickSort 代码有时会运行,但有时不会,我不知道错误发生在哪里

    unit-testing - 我应该在哪里放置我的 lib 测试

    python - 如何在 "setup"方法中使用 monkeypatch 使用 pytest 进行单元测试?

    unit-testing - 删除 JMockit 中先前定义的期望

    design-patterns - 在哪里放置不是模型但作用于模型的类

    c++ - 如何使用不同线程访问单例类成员函数?

    algorithm - 该算法的复杂度如何为 O(n^2)?

    java - 用于类别映射的高效数据结构

    Java Mockito : Cannot doReturn child classes?