lipanski / mockito

HTTP mocking for Rust!
MIT License
695 stars 59 forks source link

Mock response based on request? #159

Closed sr-gi closed 1 year ago

sr-gi commented 1 year ago

I'm wondering if there is any way of using request data in the response body. An example would be parsing the request body (json for instance) and return some of the request fields in the response body.

The only workaround for this I've been able to come up with is to .match_body and create n mocks, one per request I'm planning to send, but I'm wondering if there is a simpler solution.

lipanski commented 1 year ago

I could see something like Mock::with_body_from_request taking a Fn(Request) -> String as an argument. I wasn't too eager to expose the Request so far but the interface should be more or less stable by now.

sr-gi commented 1 year ago

I think that would make tests way less verbose, especially if multiple requests need to be analyzed.

albinocordeiro commented 1 year ago

I could see something like Mock::with_body_from_request taking a Fn(Request) -> String as an argument. I wasn't too eager to expose the Request so far but the interface should be more or less stable by now.

This would be a great feature! Is it already in place?

lipanski commented 1 year ago

it's not there yet, but it shouldn't be difficult to add. I could look into it over the next weeks but pull requests are also welcome 😉

albinocordeiro commented 1 year ago

Hi @lipanski, I wrote a working version. How do I push the branch? Do I need to fork it or would you give me permission to push and then create the PR?

lipanski commented 1 year ago

@albinocordeiro please fork the repo and open a pull request against my repo.

lipanski commented 1 year ago

@albinocordeiro I'm already tackling this in https://github.com/lipanski/mockito/pull/162 since I was planning to polish the Request inferface a little bit, but thanks for the effort.

lipanski commented 1 year ago

@sr-gi @albinocordeiro this was released in 0.32.4 - please give it a try.

sr-gi commented 1 year ago

I've tried this to generate different responses based on the path hit in the mock (as per the example provided in the PR) and it does indeed work 🎉

Is there any way of applying a matcher to the request body though, so the response is based on (or contains parts of) the body? e.g:

server
  .mock("POST", endpoint)
  .with_status(200)
  .with_header("content-type", "application/json")
  .with_body_from_request(move |request| {
      if request.body().match(...) {
          // do stuff
      } else {
          // do other stuff
      }
  })
  .create_async()
  .await;
sr-gi commented 1 year ago

No big deal if not btw, you can always build the relevant data from the request body and then match against the relevant field, but I'm wondering if there is a more idiomatic way of doing so

lipanski commented 1 year ago

@sr-gi check the documentation on matching by body https://docs.rs/mockito/latest/mockito/#matching-by-body (but also the Matcher docs)

sr-gi commented 1 year ago

@sr-gi check the documentation on matching by body https://docs.rs/mockito/latest/mockito/#matching-by-body (but also the Matcher docs)

I have, but I don't think that accomplishes what I was mentioning, does it?

Imagine the following example:

I'd like the mock to create a response based on whether a value in the request (let's say a field called value in a json body) is odd or even. For that, I can create a mock with a .match_body that contains a matcher checking the body is json encoded and contains value but not to call different functionality based on what is the value. To do that, I can use the new .with_body_from_request, but there I have no matcher to check if the body follows a certain pattern. I can build the body myself (given I know it is of a certain type based on the matching we've already performed), but not to just match here.

Again, just wondering, I think building the body myself and then matching it against a specific field is not a big deal, but I was curious whether there was an alternative to that.

albinocordeiro commented 1 year ago

@sr-gi @albinocordeiro this was released in 0.32.4 - please give it a try.

Thank you very much! I'll take it for spin :-)