lipanski / mockito

HTTP mocking for Rust!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

path matcher is sensitive to query param delimiter

imalsogreg opened this issue · comments

stripe-rs rust http client appends ? to all the paths it produces, even when it doesn't go on to specify any query parameters. The mock service we wrote for stripe failed to match because we didn't realize the client code was generating and extra '?' and that mockito would consider a path with an extra '?' to be a mismatch.

Would you be open to a PR that makes matching flexible over this case? If so, would you prefer that it simply treats /foo and /foo? identically? Or would it be better to generalize this, so that for example /foo?a=1&b=2 would accept /foo?b=2&a=1?

#[tokio::main]
async fn main() {
    let mock = mockito::mock("GET", "/hello").with_body("good bye").create();

    let url = format!("{}/hello?", mockito::server_url());
    let response = reqwest::get(url.as_str()).await.unwrap();
    mock.assert();
    println!("{:?}", response);
}
> The last unmatched request was:

GET /hello?
accept: */*
host: 127.0.0.1:1234

> Difference:

GET /hello
GET /hello?
accept: */*
host: 127.0.0.1:1234

@imalsogreg I think you have a few options as is:

(1) include the ? in the mocked path:

#[test]
fn test_trailing_question_mark() {
    let _m1 = mock("GET", "/test?").with_body("matched").create();

    let (_, _, body) = request("GET /test?", "");
    assert_eq!(body, "matched");
}

(2) use the match_query function on your Mock with either Matcher::Any or one of the other matchers, like Matcher::AnyOf or Matcher::AllOf combined with Matcher::UrlEncoded or even Matcher::Regex (check the docs/tests for some examples):

#[test]
fn test_trailing_question_mark() {
    let _m1 = mock("GET", "/test")
        .match_query(Matcher::Any)
        .with_body("matched")
        .create();

    let (_, _, body) = request("GET /test?", "");
    assert_eq!(body, "matched");

    let (_, _, other_body) = request("GET /test", "");
    assert_eq!(other_body, "matched");
}

will do this the trick for you or is there an edge case I'm missing here?

Thanks for the solutions! I should have clarified that I'm not blocked - I went with Option 1, and now I've learned about Option 2 and I can see myself using that down the road.

The question I meant to ask is - should a bare mockito path (one that doesn't involve query parameters at all) accept foo? requests? And perhaps should a bare mockito path that don't involve query parameters accept foo?bar=1 requests. My intuition from browsers and from server-side routing libraries I've used made me assume that such matches would be valid. So I'm wondering if it would be worthwhile for mockito to have that behavior.