How do I manually create an instance of reqwest::Response?

In other to be able to test a CLI that makes use of reqwest to make http calls, I am trying to abstract request so I can replace it in the test.

So far, I have defined a trait as follow:

#[async_trait]
pub trait HttpClient {
    async fn send_request(&self, path: String) -> Result<Response, Error>;
}

with an implementation for request as follows:

#[async_trait]
impl HttpClient for reqwest::Client {
    async fn send_request(&self, path: String) -> Result<Response, Error> {
        self.get(path).send().await
    }
}

This works fine and I can confirm the cli still works as it should.

Now in the test, I am stuck trying to create a mock implementation of the HttpClient as I am not sure how to construct a request::Response manually.

So far in the test I have this:

struct MockClient {
    res_req: HashMap<String, Result<Response, Error>>
}
impl MockClient {
    pub fn mock(res_req: HashMap<String, Result<Response, Error>>) -> Self {
        Self {
            res_req,
        }
    }
}

#[async_trait]
impl HttpClient for MockClient {
    async fn send_request(&self, path: String) -> Result<Response, Error> {
        self.res_req.get(path).unwrap()
    }
}

but then when I need to create an instance, not sure how to create request::Response manually. That is

    let client = MockClient::mock(
        HashMap::from(
            [("path-1".to_string(), ???)]
        ));

Any ideas?

reqwest::Responce can be created from any T: Into<Body>, Body, on the other hand, can be created from both &'static str and String. So a simple Response::from("body text") should work.

Does not seem to work...

I get

error[E0277]: the trait bound `Response: From<&str>` is not satisfied
  --> tests/integration_test.rs:30:52
   |
30 |             [("path-1".to_string(), Response::from("body text"))]
   |                                     -------------- ^^^^^^^ the trait `From<&str>` is not implemented for `Response`
   |                                     |
   |                                     required by a bound introduced by this call
   |
   = help: the trait `From<http::response::Response<T>>` is implemented for `Response`

You probably need to specify the body type

Response::<Body>::from("body text")

Sorry, my bad - that's impl From<http::Responce<T>> for Responce, not impl From<T> for Responce. This is something like reqwest::Responce::from(http::Responce::new("body text")), then.

Also does not work. new takes more than 1 arguments and it is not clear how to create those extra arguments also

Are you sure we're on the same page here? http::Responce::new takes one argument, at least in the version which is linked to from reqwest.

Question is how to access it. Trying this does not compile

error[E0433]: failed to resolve: use of undeclared crate or module `http`
  --> tests/integration_test.rs:30:55
   |
30 |             [("path-1".to_string(), Ok(Response::from(http::response::Response::new("hi"))))]
   |                                                       ^^^^ use of undeclared crate or module `http`

then using Request accessible via request fails:

error[E0061]: this function takes 4 arguments but 1 argument was supplied
  --> tests/integration_test.rs:30:55
   |
30 |             [("path-1".to_string(), Ok(Response::from(reqwest::Response::new("hi"))))]
   |                                                       ^^^^^^^^^^^^^^^^^^^^^^------ three arguments of type `Url`, `reqwest::async_impl::decoder::Accepts`, and `Option<Pin<Box<Sleep>>>` are missing

I see, sorry for the confusion - this requires adding http crate as a separate dependency.

That seems to have fixed the problem. Thanks!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.