Rocket/site/guide/testing.md

3.8 KiB

Testing

Every application should be well tested. Rocket provides the tools to perform unit and integration tests on your application as well as inspect Rocket generated code.

Tests

Rocket includes a built-in testing module that allows you to unit and integration test your Rocket applications. Testing 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:

#![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:

[dev-dependencies]
rocket = { version = "0.2.8", 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:

#[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.

Testing

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:

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

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

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

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

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

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:

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:

ROCKET_CODEGEN_DEBUG=1 cargo build

During compilation, you should see output like this:

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 generated for the hello route.