daas workshop
  • Hands-On experience building a Data as a Service Platform
  • Set Up
    • Creating a Workstation
    • Installing Tools
    • Starting Kafka
    • Congratulations
  • Module I - Overview of the DaaS Pattern
    • Section I - The Overall Pattern
    • Section II - Data Sourcing
    • Section III - Data Provisioning
    • Section IV - Data Consumption
  • Module II - Building a Rust Project
    • Section I - Create a Package
    • Section II - Creating a Library
    • Section III - Creating an Executable
    • Section IV - Creating a Hello World RESTful Endpoint
      • Section IV - manifest
      • Section IV - library
      • Section IV - module
      • Section IV - integrated testing
      • Section IV - executable
  • Module III - Building a RESTful Endpoint for Sourcing Data
    • Section I - Overview
    • Section II - manifest
    • Section III - executable
    • Section IV - starting the service
    • Section V - service testing
  • Module IV - Building a Genesis Microservice for Processing the Sourced Data
    • Section I - Overview
    • Section II - manifest
    • Section III - executable
    • Section IV - starting the service
    • Section V - service testing
  • Module V - Building a Provisioning Microservice
    • Section I - Overview
    • Section II - manifest
    • Section III - executable
    • Section IV - starting the service
    • Section V - adding the business logic
    • Section VI - testing the service
  • Module VI - Building a RESTful Endpoint for Publishing Reporting Data
    • Section I - Overview
    • Section II - manifest
    • Section III - executable
    • Section IV - starting the service
    • Section V - adding the business logic
    • Section VI - testing the service
  • Privacy Design Strategies
  • Further Exploration
Powered by GitBook
On this page

Was this helpful?

  1. Module II - Building a Rust Project
  2. Section IV - Creating a Hello World RESTful Endpoint

Section IV - module

PreviousSection IV - libraryNextSection IV - integrated testing

Last updated 4 years ago

Was this helpful?

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 from 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:8:20
  |
8 |         assert_eq!(get_service_root(), format!("/hello/{}", VER));
  |                    ^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find value `VER` in this scope
 --> src\hello_world.rs:8:61
  |
8 |         assert_eq!(get_service_root(), format!("/hello/{}", VER));
  |                                                             ^^^ not found in this scope
  |
help: consider importing this static
  |
4 |     use crate::VER;
  |

warning: unused import: `super::*`
 --> src\hello_world.rs:4:9
  |
4 |     use super::*;
  |         ^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: static is never used: `VER`
 --> src/lib.rs:4:1
  |
4 | static VER: &str = "v1";
  | ^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: 1 warning emitted

error: aborting due to 2 previous errors; 1 warning emitted

For more information about this error, try `rustc --explain E0425`.
error: could not compile `rust-daas`.

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.

ArchConfWorkshopUser:~/environment/rust-daas (master) $ cargo test
   Compiling rust-daas v0.1.0 (/home/ec2-user/environment/rust-daas)
    Finished test [unoptimized + debuginfo] target(s) in 0.89s
     Running target/debug/deps/myapp-deab36d0847aeb68

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-c97b0cb1d60cefb2

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests myapp

running 0 tests

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.

use super::*;

pub fn get_service_root() -> String {
    format!("/hello/{}", VER)
}

pub fn get_service_path() -> String {
    get_service_root() + "/"
}

#[cfg(test)]
mod tests {
    use super::*;

    #[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));
    }
}

Now that we have an understanding of how to write our tests, and then add the functionality to make them pass, we will move on to provide our service call.

Our test will be the following.

#[cfg(test)]
mod tests {
   use super::*;
   #[allow(unused_imports)]
   use actix_web::{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 req = test::TestRequest::with_header("content-type", "text/plain")
        .to_http_request();

        let resp = index(req);
        assert_eq!(resp.status(), StatusCode::OK);
    }
}

In order to make it pass, we will need to import the web service modules, and provide a index() function.

use actix_web::{HttpRequest, HttpResponse };
use actix_web::http::{StatusCode};

pub fn index(_req: HttpRequest) -> HttpResponse {
    HttpResponse::build(StatusCode::OK)
    .body("Hello World!".to_string())
}

The final file should look like the following.

use super::*;
use actix_web::{HttpRequest, HttpResponse };
use actix_web::http::{StatusCode};

pub fn get_service_root() -> String {
    format!("/hello/{}", VER)
}

pub fn get_service_path() -> String {
    get_service_root() + "/"
}

pub fn index(_req: HttpRequest) -> HttpResponse {
    HttpResponse::build(StatusCode::OK)
    .body("Hello World!".to_string())
}

mod tests {
   use super::*;
   #[allow(unused_imports)]
   use actix_web::{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 req = test::TestRequest::with_header("content-type", "text/plain")
        .to_http_request();

        let resp = index(req);
        assert_eq!(resp.status(), StatusCode::OK);
    }
}

Rerun the tests to make sure it all passes.

hello_world.rs