# Testing Every application should be well tested and understandable. Rocket provides the tools to perform unit and integration tests. It also provides a means to inspect code generated by Rocket. ## Local Dispatching Rocket applications are tested by dispatching requests to a local instance of `Rocket`. The [`local`] module contains all of the structures necessary to do so. In particular, it contains a [`Client`] structure that is used to create [`LocalRequest`] structures that can be dispatched against a given [`Rocket`] instance. Usage is straightforward: 1. Construct a `Rocket` instance that represents the application. ```rust let rocket = rocket::ignite(); ``` 2. Construct a `Client` using the `Rocket` instance. ```rust let client = Client::new(rocket).expect("valid rocket instance"); ``` 3. Construct requests using the `Client` instance. ```rust let req = client.get("/"); ``` 3. Dispatch the request to retrieve the response. ```rust let response = req.dispatch(); ``` [`local`]: https://api.rocket.rs/rocket/local/index.html [`Client`]: https://api.rocket.rs/rocket/local/struct.Client.html [`LocalRequest`]: https://api.rocket.rs/rocket/local/struct.LocalRequest.html [`Rocket`]: https://api.rocket.rs/rocket/struct.Rocket.html ## Validating Responses A `dispatch` of a `LocalRequest` returns a [`LocalResponse`] which can be used transparently as a [`Response`] value. During testing, the response is usually validated against expected properties. These includes things like the response HTTP status, the inclusion of headers, and expected body data. The [`Response`] type provides methods to ease this sort of validation. We list a few below: * [`status`]: returns the HTTP status in the response. * [`content_type`]: returns the Content-Type header in the response. * [`headers`]: returns a map of all of the headers in the response. * [`body_string`]: returns the body data as a `String`. * [`body_bytes`]: returns the body data as a `Vec`. [`LocalResponse`]: https://api.rocket.rs/rocket/local/struct.LocalResponse.html [`Response`]: https://api.rocket.rs/rocket/struct.Response.html [`status`]: https://api.rocket.rs/rocket/struct.Response.html#method.status [`content_type`]: https://api.rocket.rs/rocket/struct.Response.html#method.content_type [`headers`]: https://api.rocket.rs/rocket/struct.Response.html#method.headers [`body_string`]: https://api.rocket.rs/rocket/struct.Response.html#method.body_string [`body_bytes`]: https://api.rocket.rs/rocket/struct.Response.html#method.body_bytes These methods are typically used in combination with the `assert_eq!` or `assert!` macros as follows: ```rust let rocket = rocket::ignite(); let client = Client::new(rocket).expect("valid rocket instance"); let mut response = client.get("/").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::Plain)); assert!(response.headers().get_one("X-Special").is_some()); assert_eq!(response.body_string(), Some("Expected Body.".into())); ``` ## Testing "Hello, world!" To solidify an intuition for how Rocket applications are tested, we walk through how to test the "Hello, world!" application below: ```rust #[get("/")] fn hello() -> &'static str { "Hello, world!" } fn rocket() -> Rocket { rocket::ignite().mount("/", routes![hello]) } fn main() { rocket().launch(); } ``` Notice that we've separated the _creation_ of the `Rocket` instance from the _launch_ of the instance. As you'll soon see, this makes testing our application easier, less verbose, and less error-prone. ### Setting Up First, we'll create a `test` module with the proper imports: ```rust #[cfg(test)] mod test { use super::rocket; use rocket::local::Client; use rocket::http::Status; #[test] fn hello_world() { ... } } ``` You can also move the body of the `test` module into its own file, say `tests.rs`, and then import the module into the main file using: ```rust #[cfg(test)] mod tests; ``` ### Testing To test our "Hello, world!" application, we first create a `Client` for our `Rocket` instance. It's okay to use methods like `expect` and `unwrap` during testing: we _want_ our tests to panic when something goes wrong. ```rust let client = Client::new(rocket()).expect("valid rocket instance"); ``` Then, we create a new `GET /` request and dispatch it, getting back our application's response: ```rust let mut response = client.get("/").dispatch(); ``` Finally, we ensure that the response contains the information we expect it to. Here, we want to ensure two things: 1. The status is `200 OK`. 2. The body is the string "Hello, world!". We do this by checking the `Response` object directly: ```rust assert_eq!(response.status(), Status::Ok); assert_eq!(response.body_string(), Some("Hello, world!".into())); ``` That's it! Altogether, this looks like: ```rust #[cfg(test)] mod test { use super::rocket; use rocket::local::Client; use rocket::http::Status; #[test] fn hello_world() { let client = Client::new(rocket()).expect("valid rocket instance"); let mut response = client.get("/").dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.body_string(), Some("Hello, world!".into())); } } ``` The tests can be run with `cargo test`. You can find the full source code to [this example on GitHub](https://github.com/SergioBenitez/Rocket/tree/v0.2.8/examples/testing). ## Codegen Debug It can be useful to inspect the code that Rocket's code generation is emitting, especially when you get a strange type error. To have Rocket log the code that it is emitting to the console, set the `ROCKET_CODEGEN_DEBUG` environment variable when compiling: ```rust ROCKET_CODEGEN_DEBUG=1 cargo build ``` During compilation, you should see output like: ```rust Emitting item: fn rocket_route_fn_hello<'_b>( __req: &'_b ::rocket::Request, __data: ::rocket::Data ) -> ::rocket::handler::Outcome<'_b> { let responder = hello(); ::rocket::handler::Outcome::from(__req, responder) } ``` This corresponds to the facade request handler Rocket has generated for the `hello` route.