Guide

The ins and outs of Rocket, in detail.

Testing#

Every application should be well tested. Rocket provides the tools to unit test your application and inspect Rocket generated code.

Unit Tests#

Rocket includes a built-in testing module that allows you to unit test your Rocket applications. The testing methadology is simple:

  1. Construct a Rocket instance.
  2. Construct a MockRequest.
  3. Dispatch the request using the Rocket instance.
  4. Inspect, validate, and verify the Response.

After setting up, we’ll walk through each of these steps for the “Hello, world!” program below:

1
2
3
4
5
6
7
8
9
#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;

#[get("/")]
fn hello() -> &'static str {
    "Hello, world!"
}

Setting Up#

For the testing module to be available, Rocket needs to be compiled with the testing feature enabled. Since this feature should only be enabled when your application is compiled for testing, the recommended way to enable the testing feature is via Cargo’s [dev-dependencies] section in the Cargo.toml file as follows:

1
2
[dev-dependencies]
rocket = { version = "0.1.5", features = ["testing"] }

With this in place, running cargo test will result in Cargo compiling Rocket with the testing feature, thus enabling the testing module.

You’ll also need a test module with the proper imports:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#[cfg(test)]
mod test {
  use super::rocket;
  use rocket::testing::MockRequest;
  use rocket::http::{Status, Method};

  #[test]
  fn hello_world() {
    ...
  }
}

In the remainder of this section, we’ll work on filling in the hello_world testing function to ensure that the hello route results in a Response with “Hello, world!” in the body.

Rocket Instance#

We’ll begin by constructing a Rocket instance with the hello route mounted at the root path. We do this in the same way we would normally with one exception: we need to refer to the testing route in the super namespace:

1
let rocket = rocket::ignite().mount("/", routes![super::hello]);

Create Request#

Next, we create a MockRequest that issues a Get request to the "/" path:

1
let mut req = MockRequest::new(Method::Get, "/");

The MockRequest object needs to be mut for the next section.

Dispatch#

We now ask Rocket to perform a full dispatch, which includes routing, pre-processing and post-processing, and retrieve the Response:

1
let mut response = req.dispatch_with(&rocket);

The Response object needs to be mut for the next section.

Validate#

Finally, we can test the Response values to ensure that it contains the information we expect it to. We want to ensure two things:

  1. The status is 200 OK.
  2. The body is the string “Hello, world!”.

We do this by querying the Response object directly:

1
2
3
4
assert_eq!(response.status(), Status::Ok);

let body_str = response.body().and_then(|b| b.into_string());
assert_eq!(body_str, Some("Hello, world!".to_string()));

That’s it! Run the tests with cargo test. The complete application, with testing, can be found in the GitHub testing example.

Codegen Debug#

It is sometimes 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:

1
ROCKET_CODEGEN_DEBUG=1 cargo build

During compilation, you should see output like this:

1
2
3
4
5
6
7
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::of(responder)
}

This corresponds to the facade request handler Rocket generated for the hello route.