The integration testing client

Add the following struct to your utils.rs source file:

pub struct WebApi {
client: Client,
url: String,
jar: CookieJar,
}

It has three fields—an HTTP Client; a base url, which is used to construct full URLs with added paths; and a CookieJar instance to keep cookie values between requests.

The constructor of this struct takes a URL and builds a Client instance with redirects disabled:

impl WebApi {
fn new(url: &str) -> Self {
let client = Client::builder()
.redirect(RedirectPolicy::none())
.build()
.unwrap();
Self {
client,
url: url.into(),
jar: CookieJar::new(),
}
}
}

We can add shortcuts to create instances of WebApi for the specific microservice of our application:

pub fn users() -> Self { WebApi::new(USERS) }
pub fn mailer() -> Self { WebApi::new(MAILER) }
pub fn content() -> Self { WebApi::new(CONTENT) }
pub fn router() -> Self { WebApi::new(ROUTER) }

We will check that every microservice is alive. To do this, we need a method for WebApi that sends GET requests to a specified path and checks the response:

pub fn healthcheck(&mut self, path: &str, content: &str) {
let url = url(&self.url, path);
let mut resp = reqwest::get(&url).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let text = resp.text().unwrap();
assert_eq!(text, content);
}

Every microservice of our application has a special path to get the name of microservice, which we will use for health-checking.

To send requests to microservices, we will use the following function:

pub fn request<'a, I, J>(&mut self, method: Method, path: &'a str, values: I) -> J
where
I: IntoIterator<Item = (&'a str, &'a str)>,
J: for <'de> Deserialize<'de>,
{
let url = url(&self.url, path);
let params = values.into_iter().collect::<HashMap<_, _>>();
let mut resp = self.client.request(method, &url)
.form(&params)
.send()
.unwrap();

let status = resp.status().to_owned();

let text = resp
.text()
.unwrap();

if status != StatusCode::OK {
panic!("Bad response [{}] of '{}': {}", resp.status(), path, text);
}

let value = serde_json::from_str(&text);
match value {
Ok(value) => value,
Err(err) => {
panic!("Can't convert '{}': {}", text, err);
},
}
}

It's a useful function that sends a request in JSON format and receives a response in JSON format, which it deserializes into the necessary native struct. The implementation of this method is not crazy. It expects a HTTP method, path, and values that will be used as form parameters in a request.

We use a textual response to print values if the microservice returns an HTTP status other than OK. If a response is successful, we will deserialize the body from JSON format to the necessary output type.

Since the whole application won't return internal service information to us, we need a method that creates a request and checks the status code of a response, but also stores cookies to have a chance to sign up and sign in to our application. Create the check_status method for the WebApi struct implementation:

pub fn check_status<'a, I>(&mut self, method: Method, path: &'a str, values: I, status: StatusCode)
where
I: IntoIterator<Item = (&'a str, &'a str)>,
{
let url = url(&self.url, path);
let params = values.into_iter().collect::<HashMap<_, _>>();
let cookies = self.jar.iter()
.map(|kv| format!("{}={}", kv.name(), kv.value()))
.collect::<Vec<_>>()
.join(";");
let resp = self.client.request(method, &url)
.header(COOKIE, cookies)
.form(&params)
.send()
.unwrap();
if let Some(value) = resp.headers().get(SET_COOKIE) {
let raw_cookie = value.to_str().unwrap().to_owned();
let cookie = Cookie::parse(raw_cookie).unwrap();
self.jar.add(cookie);
}
assert_eq!(status, resp.status());
}

The preceding implementation also uses values to make a request with a form, but it also prepares cookies and sends them with the Cookie  header after the function expects a response from a server. If a response contains a SetCookie header, we use it to update our CookieJar. With such simple manipulations, we take a method that can keep the connection session.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.235.62