LukeMathWalker / wiremock-rs

HTTP mocking to test Rust applications.
Apache License 2.0
607 stars 69 forks source link

Response template extensions #115

Closed the-wondersmith closed 1 year ago

the-wondersmith commented 1 year ago

Issue #, if available: N/A

Description of changes: -

PR adds a Default impl and set_status_code method to the wiremock::ResponseTemplate struct. The intention of the change is to support abstracting / encapsulating repetitive response creation into discrete functions. For example, writing tests for a client library whose target API always returns a JSON response of some kind but whose responses are only almost always 200.

For example, given:

use http::StatusCode;
use http_types::{headers::CONTENT_TYPE, mime::JSON};
use wiremock::{
    http::{HeaderName, HeaderValue},
    Request, ResponseTemplate,
};

const FIELD_ERROR: &str = r#"{"errors":{"default":"invalid or missing query parameter"}}"#;
const AUTH_KEY_ERROR: &str = r#"{"errors": {"user": "not authorized or over daily test limit for untrusted domains"}}"#;

fn field_error_response(_: &Request) -> ResponseTemplate {
    ResponseTemplate::new(StatusCode::BAD_REQUEST).set_body_raw(FIELD_ERROR, &JSON.to_string())
}

fn bad_api_key_response(_: &Request) -> ResponseTemplate {
    ResponseTemplate::new(StatusCode::UNAUTHORIZED).set_body_raw(AUTH_KEY_ERROR, &JSON.to_string())
}

Some of the repetition in the two response functions can be abstracted into a common function like:

fn raw_json_response(from: &'static str) -> ResponseTemplate {
    ResponseTemplate::default().set_body_raw(from, &JSON.to_string())
}

which then allows users to write the two responders above as:

fn field_error_response(_: &Request) -> ResponseTemplate {
    raw_json_response(FIELD_ERROR).set_status_code(StatusCode::BAD_REQUEST)
}

fn bad_api_key_response(_: &Request) -> ResponseTemplate {
    raw_json_response(AUTH_KEY_ERROR).set_status_code(StatusCode::UNAUTHORIZED)
}

Granted, this example is extremely trivial and doesn't appear to save a ton of code. (Also, yes, I know the set_body_json method basically does almost exactly this). In my specific case it does actually end up saving a non-trivial amount of code / boilerplate / repetition, so I figured I couldn't be the only one in that boat ¯\(ツ)/¯.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

LukeMathWalker commented 1 year ago

I'm afraid I'll need some of those non-trivial examples to be persuaded that this PR should be accepted 👀

the-wondersmith commented 1 year ago

@LukeMathWalker That's fair. TBH, all of the examples I've got in my actual codebase are like... right on the line between trivial and non-trivial. The use case is stemming from what a PITA it's proving to be to write tests for a REST API client library for a service that does publish its API docs as a Postman collection (and therefore has "official" deterministic request/response examples) but that I don't actually have anything to do with. I find myself repeating the same code a lot with the only change being a single variable name.

The tl;dr here is the addition allowed me to abstract a several of the repetitions out, but the whole shebang is still pretty repetitive regardless so this PR may just be my extra gene acting up 🙄. If I can't find some objectively non-trivial use case examples to share within the next few days I'll chalk it up to exactly that and just close the PR. 😅