#rust
#Ржавчина
Вопрос:
Я читаю книгу Rust и работаю над частью minigrep, где он просит вас написать несколько модульных тестов для Config::new
функции. Я терплю неудачу в том, чего не ожидал, и не понимаю, почему (Google-fu также подводит меня).
Это не удается
#[cfg(test)]
mod new_config_tests {
use super::*;
#[test]
fn it_can_create_a_new_config() {
let expected_query = "expected_qury";
let expected_filename = "expected_filename.txt";
let args: Vec<String> = vec!["program/path".to_string(), expected_query.to_string(), expected_filename.to_string()];
// failing line
let actual = Config::new(amp;args).unwrap_or_else(|err| { assert!(false); });
}
}
impl Config {
pub fn new(args: amp;[String]) -> Result<Config, amp;'static str> {
if args.len() < 3 {
return Err("not enough argumentsn");
}
let query = args[1].clone();
let filename = args[2].clone();
Ok(Config { query, filename })
}
}
с
error[E0308]: mismatched types
--> src/lib.rs:19:62
|
19 | let actual = Config::new(amp;args).unwrap_or_else(|err| { assert!(false); });
| ^^^^^^^^^^^^^^^^^^^ expected struct `Config`, found `()`
В этом тесте я просто удостоверяюсь, что могу создать новое Config
и хочу, чтобы оно завершилось с ошибкой, если Config::new
функция завершится с ошибкой. Я думал, что использование assert
будет правильным, чтобы тестовая среда обработала сбой. Если я изменю значение assert
на panic
, тесты пройдут, как и ожидалось. Правильно ли использовать panic в приведенном выше сценарии?
Комментарии:
1. Вы также можете вернуть a
Result
в тестах: doc.rust-lang.org/edition-guide/rust-2018 /… Это позволило бы вам писатьlet actual = Config::new(amp;args)?;
вместо этого.
Ответ №1:
Проблема в том, что во время проверки типов компилятор (пока) не понимает, что assert!(false)
это всегда приведет к сбою, поэтому он должен предположить, что он может пройти, что приведет к значению type ()
, которое несовместимо с ожидаемым Config
типом.
И наоборот, если вы заменяете assert вызовом to panic
, компилятор знает, что panic
это никогда не возвращается, поэтому не имеет значения, есть ли нет Config
возврата. (Строго говоря, panic
typechecks возвращает значение type !
, иначе тип «never», который совместим со всем).
IMO вы никогда не должны использовать assert!(false)
, а вместо этого использовать panic
, когда знаете, что условие всегда фатально. Это делает ваше намерение более понятным.
Хотя в этом конкретном случае, вероятно, было бы лучше утверждать, что результат Ok
:
assert!(Config::new(amp;args).is_ok());
Комментарии:
1. Примечание: ожидаемый тип вывода — это
Config
, а не aResult
.2. Хорошо, я думаю, что понимаю. Я все еще новичок в Rust, некоторые из упомянутых мной вещей — это магия, но в конце концов я научусь этому.