Клиент Reqwest::new зависает в тесте с Iron во втором потоке

Я использую Reqwest в своем веб-сканере и пытаюсь добавить тесты для основного цикла, чтобы убедиться, что я получаю правильный вывод. Я пытаюсь использовать Iron для поддельного HTTP-сервера с предустановленными ответами. Однако по моему main_loop функция, let client = Client::new(); висит.

Первые несколько строк _main_loop:

fn _main_loop(starton: String, panic: bool) {
    //panic("test") // calls as normal
    let client = Client::new(); // <-- problem!
    panic("test") // doesn't call
    let mut future_urls: Vec<String>;
    // ...
}

Мой тест mod:

#[cfg(test)]
mod tests {
    use iron::{Iron, IronResult, Headers};
    use iron::response::Response;
    use iron::request::Request;
    use iron::status;
    use iron::middleware::Chain;
    use iron::headers::ContentType;
    use iron::mime::{Mime, TopLevel, SubLevel};
    use iron::typemap::TypeMap;
    use std;

    use *;

    #[test]
    fn __main_loop() {
        fn handler(req: &mut Request) -> IronResult<Response> {
            let mut mime = Headers::new();
            mime.set(ContentType(Mime(TopLevel::Text, SubLevel::Html, Vec::new())));

            Ok(Response {
                headers: mime,
                status: Some(status::Ok),
                body: Some(Box::new(match req.url.path().join("/").as_str() {
                "" => "<a href='file'></a><a href='file1'></a>",
                "file" => "<a href='/file1'></a>",
                "file1" => "<a href='/file'></a>",
                _ => "not found"
                })),
                extensions: TypeMap::new()
            })
        }

        let child = std::thread::spawn(|| Iron::new(Chain::new(handler)).http("localhost:9999").unwrap());

        let f: Vec<String> = Vec::new();
        assert_eq!(_main_loop("http://localhost:9999/".to_string(), false), f);
    }
}

Терминальный выход:

$ cargo test
   Compiling crawler v1.0.0 (file:///home/*******/crawler)
warning: unreachable statement
  --> src/main.rs:82:5
   |
82 |     let mut future_urls: Vec<String>;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: #[warn(unreachable_code)] on by default

warning: unused variable: `client`
  --> src/main.rs:80:9
   |
80 |     let client = Client::new();
   |         ^^^^^^ help: consider using `_client` instead
   |
   = note: #[warn(unused_variables)] on by default

warning: unused variable: `starton`
  --> src/main.rs:79:15
   |
79 | fn _main_loop(starton: String, _panic: bool) -> Vec<String> {
   |               ^^^^^^^ help: consider using `_starton` instead

warning: unused variable: `child`
   --> src/main.rs:239:13
    |
239 |         let child = std::thread::spawn(|| Iron::new(Chain::new(handler)).http("localhost:9999").unwrap());
    |             ^^^^^ help: consider using `_child` instead

    Finished dev [unoptimized + debuginfo] target(s) in 4.24 secs
     Running target/debug/deps/crawler-9c5de394eb85849d

running 9 tests
test html::tests::_get_attribute_for_elem ... ok
test html::tests::_html_token_sink ... ok
test url_utils::tests::_add_url_to_vec ... ok
test url_utils::tests::_get_root_domain ... ok
test html::tests::_find_urls_in_html ... ok
test url_utils::tests::_check_if_is_in_url_list ... ok
test url_utils::tests::_remove_get_params ... ok
test url_utils::tests::_repair_suggested_url ... ok

При выполнении теста однопоточный (-- --test-threads 1), заканчивается test tests::__main_loop ...,

1 ответ

Я думаю, что проблема заключается в том, что созданный вами поток не завершается, а тест завершается в ожидании его завершения (я не уверен, почему это происходит, и через некоторое время он не будет уничтожен исполнителем теста), т.е. проблема не в reqwest, а в вашем железном сервере.

Теперь я не уверен, как это исправить, на самом деле Listening::close кажется, сломан, так как железо 0.6.0 все еще зависит от гипер 0.10, который больше не имеет этой функциональности.

В худшем случае вы можете реализовать сервер, используя Hyper, как я сделал здесь. Может быть, есть действительно быстрое решение для вашего исходного кода, я не знаю.

Обычно, если вы можете найти способ запустить сервер в своих тестах, это, на мой взгляд, идеальный случай. С ящиком я связался раньше (reqwest-mock Отказ от ответственности я автор) вы могли бы написать свой _main_loop функция взять GenericClient в качестве аргумента, а затем смоделируйте запрос в ваших тестах, используя StubClient и используйте прямой клиент в производственном коде. Но, возможно, вам это даже не нужно, и вы должны стремиться спроектировать свой сканер таким образом, чтобы вы могли тестировать различные функции как можно более независимо друг от друга.

Другие вопросы по тегам