I'm currently writing a REST web server with Rust.
I'm using "reqwest" to test the REST API. To get these tests running, I need to have an instance of the server running.
If I launch it before running "cargo test", cargo fails as it can overwrite the binary (on Windows)
So, I've tried to:
For 1), I've found several solution (test_env_helpers, Once, ...) But for 2), I haven't found a solution. I've tried:
Any suggestion?
One solution is to use an integration test. During cargo test
, they're compiled separately from and have access to the server binary. You're responsible for figuring out the path to the binary, though. On supported operating systems, libc::atexit
allows killing the server after tests have concluded.
// tests/test_server.rs
use libc::atexit;
use std::io::{BufRead, BufReader};
use std::process::{Child, Command, Stdio};
use std::sync::Mutex;
pub fn ensure_server_started() {
static STARTED: Mutex<Option<Child>> = Mutex::new(None);
let mut started = STARTED.lock().unwrap();
if started.is_some() {
return;
}
let mut path = std::env::current_exe().unwrap();
assert!(path.pop());
if path.ends_with("deps") {
assert!(path.pop());
}
// Note: Cargo automatically builds this binary for integration tests.
path.push(format!(
"{}{}",
env!("CARGO_PKG_NAME"),
std::env::consts::EXE_SUFFIX
));
let mut cmd = Command::new(path);
cmd.env_clear();
cmd.stdin(Stdio::piped());
cmd.stdout(Stdio::piped());
cmd.stderr(Stdio::piped());
// TODO: cmd.args([]);
let mut server = cmd.spawn().unwrap();
let stdout = server.stdout.take().unwrap();
let reader = BufReader::new(stdout);
let mut lines = reader.lines();
let mut listening = false;
while let Some(Ok(line)) = lines.next() {
// TODO: Server needs to print "listening" to stdout
if line.contains("listening") {
listening = true;
break;
}
}
assert!(listening);
extern "C" fn kill() {
STARTED.lock().unwrap().as_mut().unwrap().kill().unwrap();
}
unsafe { atexit(kill) };
*started = Some(server);
}
#[test]
pub fn test_server() {
// Beginning of every test.
ensure_server_started();
// TODO: Test
}