alexliesenfeld / httpmock

HTTP mocking library for Rust
https://httpmock.rs
MIT License
488 stars 45 forks source link

Mocking retries? #96

Open jamesperez2005 opened 10 months ago

jamesperez2005 commented 10 months ago

I'm trying to mock a service that is supposed to be called multiple times and fail, and then succeed at the Nth time. Since these are retries the requests should be the same, so there's no way to distinguish them by parameters or by path/body.

Is that something that can be done with httpmock?

alexliesenfeld commented 10 months ago

Hi @jamesperez2005 , thanks for reaching out!

Do you think delete will help you here?


#[test]
fn delete_mock_test() {
    let server = MockServer::start();

    let mut m1 = server.mock(|when, then| {
        when.method(GET).path("/test");
        then.status(500);
    });

    let mut m2 = server.mock(|when, then| {
        when.method(GET).path("/test");
        then.status(200);
    });

    let response = get(&format!(
        "http://{}:{}/test",
        server.host(),
        server.port()
    ))
    .unwrap();

    assert_eq!(response.status(), 500);

    // As long as both m1 and m2 exist, m1 will take precedence over m2. 
    // Let's delete m1 so we can respond with a successful response.
    m1.delete();

    let response = get(&format!("http://{}/test", server.address())).unwrap();

    assert_eq!(response.status(), 200);
}
jamesperez2005 commented 10 months ago

Not quite. I want to test a utility function that does the retries by itself, so I don't get a chance to intervene after the first N retries... It would be great to have a "match_at_most(N)" helper on the when clause, or even provide a callback to control what happens based on a variable

alexliesenfeld commented 6 months ago

Interesting idea ... OK, let's keep this issue open and I'll try to get a PR for it after the next release (it's a big change, so it makes sense to wait a bit).

mothran commented 3 weeks ago

Until #108 lands here is a (ugly) work around to mock failing the first request:

static mut REQ_COUNT: u32 = 0;
...
let server = MockServer::start();
let get_mock = server.mock(|when, then| {
    when.method(GET).path("/test").matches(|_req: &HttpMockRequest| {
        let req = unsafe {
            let req = REQ_COUNT;
            REQ_COUNT += 1;
            req
        };
        req >= 1
    });
    then.status(200).body("TEST");
});

Its not pretty but is a reasonable workaround.