Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot import a module in an integration test

Tags:

rust

I am trying to configure an example project in Rust to work.

My structure is:

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

And my Cargo.toml

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

My potter.rs contains:

pub mod potter {
    pub struct Potter {

    }

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

}

And my tests.rs contains:

use potter::Potter;

    #[test]
    fn it_works() {

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

But I receive this error:

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

If I add extern crate potter;, it doesn't fix anything...

error[E0463]: can't find crate for `potter`
 --> tests/tests.rs:1:1
  |
1 | extern crate potter;
  | ^^^^^^^^^^^^^^^^^^^^ can't find crate
like image 775
carlos.baez Avatar asked Oct 21 '17 20:10

carlos.baez


1 Answers

Go back and reread The Rust Programming Language about packages, crates, modules and the filesystem.

Common pain points:

  • Every programming language has its own way of dealing with files — you cannot just assume that because you've used any other language that you will magically get Rust's take on it. That's why you should go back and re-read the book chapter on it.

  • Each file defines a module. Your lib.rs defines a module of the same name as your crate; a mod.rs defines a module of the same name as the directory it's in; every other file defines a module of the name of the file.

  • The root of your library crate must be lib.rs; binary crates may use main.rs.

  • No, you really shouldn't try to do non-idiomatic filesystem organization. There are tricks to do most anything you want; these are terrible ideas unless you are already an advanced Rust user.

  • Idiomatic Rust does not generally place "one type per file" like many other languages. Yes, really. You can have multiple things in one file.

  • Unit tests usually live in the same file as the code it's testing. Sometimes they will be split out into a file containing the submodule, but that's uncommon.

  • Integration tests, examples, benchmarks all have to import the crate like any other user of the crate and can only use the public API.


To fix your issue:

  1. Move your src/potter.rs to src/lib.rs.
  2. Remove pub mod potter from src/lib.rs. Not strictly required, but removes needless nesting of modules.
  3. Add extern crate potter to your integration test tests/tests.rs.

filesystem

├── 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);
}
like image 51
Shepmaster Avatar answered Sep 19 '22 19:09

Shepmaster