【问题标题】:Cannot import a module in an integration test无法在集成测试中导入模块
【发布时间】:2020-06-08 22:50:44
【问题描述】:

我正在尝试使用 Rust 配置一个示例项目。

我的结构是:

  • src/potter.rs
  • tests/tests.rs

还有我的Cargo.toml

[package]
name = "potter"
version = "0.1.0"
authors = ["my name"]
[dependencies]

我的potter.rs 包含:

pub mod potter {
    pub struct Potter {

    }

    impl Potter  {
        pub fn new() -> Potter {
         return Potter {};
        }
    }

}

我的tests.rs 包含:

use potter::Potter;

    #[test]
    fn it_works() {

        let pot = potter::Potter::new();
        assert_eq!(2 + 2, 4);
    }

但我收到此错误:

error[E0432]: unresolved import `potter`
 --> tests/tests.rs:1:5
  |
1 | use potter::Potter;
  |     ^^^^^^ Maybe a missing `extern crate potter;`?

error[E0433]: failed to resolve. Use of undeclared type or module `potter`
 --> tests/tests.rs:6:19
  |
6 |         let pot = potter::Potter::new();
  |                   ^^^^^^ Use of undeclared type or module `potter`

warning: unused import: `potter::Potter`
 --> tests/tests.rs:1:5
  |
1 | use potter::Potter;
  |     ^^^^^^^^^^^^^^
  |
  = note: #[warn(unused_imports)] on by default

如果我添加extern crate potter;,它不会解决任何问题...

error[E0463]: can't find crate for `potter`
 --> tests/tests.rs:1:1
  |
1 | extern crate potter;
  | ^^^^^^^^^^^^^^^^^^^^ can't find crate

【问题讨论】:

  • 我删除了pub mod potter,错误仍然存​​在。
  • 我从重复的答案中应用了解决方案,它似乎不起作用。
  • 我将我的 potter.rs 重命名为 lib.rs 但它一直无法正常工作...

标签: rust


【解决方案1】:

返回并reread The Rust Programming Language about packages, crates, modules and the filesystem。

常见痛点:

  • 每种编程语言都有自己处理文件的方式——你不能只是假设因为你使用过任何其他语言,你就会神奇地得到 Rust 的接受。这就是为什么你应该go back and re-read the book chapter on it。

  • 每个文件定义一个模块。您的 lib.rs 定义了一个与您的 crate 同名的模块; mod.rs 定义了一个与其所在目录同名的模块;每个其他文件都定义了一个文件名的模块。

  • 你的库包的根必须是lib.rs;二进制包可以使用main.rs。

  • 不,你真的不应该尝试做非惯用的文件系统组织。有一些技巧可以做任何你想做的事情;除非您已经是 Rust 高级用户,否则这些想法很糟糕。

  • 惯用的 Rust 通常不像许多其他语言那样放置“每个文件一个类型”。对真的。您可以在一个文件中包含多个内容。

  • 单元测试通常与其测试的代码位于同一个文件中。有时它们会被拆分成一个包含子模块的文件,但这并不常见。

  • 集成测试、示例、基准测试都必须像任何其他 crate 用户一样导入 crate,并且只能使用公共 API。


解决您的问题:

  1. 将您的src/potter.rs 移至src/lib.rs。
  2. 从src/lib.rs 中删除pub mod potter。 严格不是必需的,但删除了不必要的模块嵌套。
  3. 将extern crate potter 添加到您的集成测试tests/tests.rs。

文件系统

├── Cargo.lock
├── Cargo.toml
├── src
│   └── lib.rs
├── target
└── tests
    └── tests.rs

src/lib.rs

pub struct Potter {}

impl Potter {
    pub fn new() -> Potter {
       Potter {}
    }
}

tests/tests.rs

use potter::Potter;

#[test]
fn it_works() {
    let pot = Potter::new();
    assert_eq!(2 + 2, 4);
}

【讨论】:

  • 我有 tests/common.rs 我正在这样做:#[macro_use] extern crate mylib; 但它说 "an extern crate 加载宏 必须在板条箱根".所以我想知道 tests 目录的 "crate root" 是哪个文件?有没有类似 src/lib.rs 的?
  • @Nawaz tests 目录中的每个文件都被编译为单独的二进制包。其中每一个都是 crate 根。另见Where should I put test utility functions in Rust?; What is an idiomatic way to have shared utility functions for integration tests and benchmarks?.
  • 那么为什么#[macro_use] extern ... 不适用于tests/common.rs,它要求我输入一些crate root。 crate root 是什么,似乎没有明确定义。
  • 因为你还没有把它放在 crate 根目录下。 “crate root”是一个定义明确的术语——它是 crate 的入口点。 tests 目录中的每个文件 都被编译为单独的二进制 crate。这意味着您的 tests/common.rs 正在编译为二进制文件,因此这是一个 crate 根(可能也不是您想要的)。大概您还将该文件作为模块从另一个文件(如tests/foo.rs)导入 - foo.rs 也是一个板条箱根。
  • 我将所有内容从tests/common.rs 移动到tests/common/mod.rs,现在我可以在其他测试文件中执行mod common;。有用。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-03
  • 2020-10-02
  • 2021-10-27
  • 2014-09-17
  • 2020-06-04
  • 2020-06-16
相关资源
最近更新 更多