To create the module, create a new file named hello_world.rs in the /src directory.
To begin, we will follow some basic TDD practices and build our tests first.
NOTE: This is not a TDD workshop, so we will ignore the complete practices and simply illustrate how it would be done.
At the bottom of the file, create an empty nested testing module. This will be where we write our unit test for the hello_world module. The use super::*; line imports all the functionality and variables form the parent hello_world module.
#[cfg(test)]
mod tests {
use super::*;
}
Our first test will be to return the service root. Add the following test in tests module below the use super::; line so it looks like the following.
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_service_root() {
assert_eq!(get_service_root(), format!("/hello/{}", VER));
}
}
Following TDD practices, we now run our test and confirm that it will fail.
[user@localhost rust-daas]$ cargo test
Compiling rust-daas v0.1.0 (C:\tmp\rust-daas)
error[E0425]: cannot find function `get_service_root` in this scope
--> src\hello_world.rs:10:20
|
10 | assert_eq!(get_service_root(), format!("/hello/{}", VER));
| ^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `test_get_service_root`
warning: unused imports: `App`, `HttpRequest`, `Responder`
--> src\hello_world.rs:2:17
|
2 | use actix_web::{App, HttpRequest, Responder};
| ^^^ ^^^^^^^^^^^ ^^^^^^^^^
|
= note: #[warn(unused_imports)] on by default
error: aborting due to previous error
For more information about this error, try `rustc --explain E0425`.
error: Could not compile `rust-daas`.
To learn more, run the command again with --verbose.
To make the test pass, we will add the get_service_root() function to the module.
use super::*;
pub fn get_service_root() -> String {
format!("/hello/{}", VER)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_service_root() {
assert_eq!(get_service_root(), format!("/hello/{}", VER));
}
}
If we rerun our test, it will now pass.
[user@localhost rust-daas]$ cargo test
Compiling rust-daas v0.1.0 (C:\tmp\rust-daas)
Finished dev [unoptimized + debuginfo] target(s) in 1.60s
Running target\debug\deps\daas-dafe2c98359dbcd2.exe
running 1 test
test hello_world::tests::test_get_service_root ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Running target\debug\deps\hello_world-f32c48dd7c679e2e.exe
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Doc-tests daas
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
We will do the same for the get_service_path() function.
Now that we have an understanding of how to write our tests, and then add the funcitonality to make them pass, we will move on to provide our service call.
Our test will be the following.
mod tests {
use super::*;
use actix_web::{http, test};
#[test]
fn test_get_service_root() {
assert_eq!(get_service_root(), format!("/hello/{}", VER));
}
#[test]
fn test_get_service_path() {
assert_eq!(get_service_path(), format!("/hello/{}/", VER));
}
#[test]
fn hello_response() {
let resp = test::TestRequest::with_header("content-type", "text/plain")
.run(&index)
.unwrap();
assert_eq!(resp.status(), http::StatusCode::OK);
}
}
In order to make it pass, we will need to import the web service modules, and provide a index() function.
We now have one last step, which is to add a function that will provide the service object. This is will nor be covered by unit testing and is instead covered by integrated testing.
To create integrated tests, first create a new file named web-service-tests.rs in a new directory named tests in the root path (same level as the src directory). Cargo will automatically parse the tests directory and run any tests that are located in any files located here.
In order to execute our service test, we will first need to include the bytes library to our project. We do this by adding the line bytes = "0.4" in the [dependencies] section of the Cargo.toml file.
Once the library has been included in the Manifest, we define which libraries are required in the web-service-tests module by adding the following lines at the top of the web-service-tests.rs file.
extern crate actix_web;
extern crate bytes;
The extern declarations specify the dependent crates (or libraries) that will be used in the web-service-tests module.
We then declare the bindings (or shortcuts) to a resources that will be used in the web-service-tests module. This is done by adding the following lines below the extern crate declarations.
use daas::hello_world;
use actix_web::*;
use http::header;
use bytes::Bytes;
Now we can add the code for our Hello World service test, which is added below the use declarations.
#[test]
fn test_hello_world_ok() {
let mut srv =actix_web::test::TestServer::new(|app| app.handler(hello_world::index));
let request = srv.get().uri(srv.url("/").as_str()).finish().unwrap();
let response = srv.execute(request.send()).unwrap();
assert!(response.status().is_success());
// read response
let bytes = srv.execute(response.body()).unwrap();
assert_eq!(bytes, Bytes::from_static("Hello World!".as_ref()));
}
At this point the web-service-tests.rs file should look like this:
extern crate actix_web;
extern crate bytes;
use daas::hello_world;
use actix_web::*;
use http::header;
use bytes::Bytes;
#[test]
fn test_hello_world_ok() {
let mut srv =actix_web::test::TestServer::new(|app| app.handler(hello_world::index));
let request = srv.get().uri(srv.url("/").as_str()).finish().unwrap();
let response = srv.execute(request.send()).unwrap();
assert!(response.status().is_success());
// read response
let bytes = srv.execute(response.body()).unwrap();
assert_eq!(bytes, Bytes::from_static("Hello World!".as_ref()));
}
Try running your test with the cargo test command. There should now be a line in the results referencing that the web_service_tests has run.
Running target\debug\deps\web_service_tests-664800ae8a37eeb0.exe
running 1 test
test test_hello_world_ok ... ok