I am trying to build a basic terminal utility. This terminal utility uses Telegram bot API under the hood and I use clap to implement this utility.
Since the application uses real HTTP server to operate, I thought it would be better to mock the HTTP. Then I have found mockito and this amazing article showing how to test terminal applications.
I have tried to glue them together. Firstly, I get the API URL as below:
// related imports
#[cfg(not(test))]
fn get_base_url<'a>() -> &'a str {
"https://api.telegram.org/bot"
}
#[cfg(test)]
fn get_base_url<'a>() -> &'a str {
mockito::SERVER_URL
}
As you might have guessed, the first get_base_url
function is compiled into binary when it is not test while the second one is compiled in testing environment.
I do not know if relevant but here is my integration test in tests/bot.rs
directory:
#[test]
fn test_successful_authentication() {
let _m = mock("POST", "/foo/getMe")
.with_body_from_file("tests/resources/getMe.1.json")
.create();
let out = process::Command::new("./target/debug/tgcli")
.arg("bot")
.arg("-t")
.arg("foo")
.output()
.expect("failed to execute tgcli");
let out_text = String::from_utf8_lossy(&out.stdout);
println!("{}", out_text);
assert!(out_text.contains("Bot authenticated successfully.")) // fails here
}
Test fails on assertion. I have put a println!
over there to see what the content is. Thanks to log and fern, I have seen what URL reqwest was requesting and it was the real API URL.
Do you know why #[cfg(test)]
does not compile while running integration tests?
Thanks in advance.
Environment
- cargo 1.40.0
- rustc 1.40.0
Dependencies
[dependencies]
clap = "2.33.0"
log = "0.4.8"
fern = "0.5.9"
chrono = "0.4.10"
reqwest = { version = "0.10.0", features = ["blocking"] }
serde = "1.0.104"
serde_json = "1.0.44"
[dev-dependencies]
mockito = "0.22.0"