Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mocking multipart uploads #39

Closed
ayrat555 opened this issue Apr 18, 2021 · 6 comments
Closed

Mocking multipart uploads #39

ayrat555 opened this issue Apr 18, 2021 · 6 comments

Comments

@ayrat555
Copy link

ayrat555 commented Apr 18, 2021

It seems the library fails on multipart/form-data uploads. It works fine with regular requests with json body.

Requests to real server upload files without any issues. I'm using ureq as HTTP client:

    fn request_with_form_data<T1: serde::ser::Serialize, T2: serde::de::DeserializeOwned>(
        &self,
        method: &str,
        params: T1,
        parameter_name: &str,
        file_path: PathBuf,
    ) -> Result<T2, ureq::Error> {
        let json_string = serde_json::to_string(&params).unwrap();
        let json_struct: Value = serde_json::from_str(&json_string).unwrap();

        let mut form = Multipart::new();
        for (key, val) in json_struct.as_object().unwrap().iter() {
            if key != parameter_name {
                let val = match val {
                    &Value::String(ref val) => format!("{}", val),
                    etc => format!("{}", etc),
                };

                form.add_text(key, val);
            }
        }

        let file = std::fs::File::open(&file_path).unwrap();
        let file_extension = file_path.extension().and_then(|s| s.to_str()).unwrap_or("");
        let mime = mime_guess::from_ext(&file_extension).first_or_octet_stream();

        form.add_stream(
            parameter_name,
            file,
            file_path.file_name().unwrap().to_str(),
            Some(mime),
        );

        let url = format!("{}/{}", self.api_url, method);
        let form_data = form.prepare().unwrap();

        let response = ureq::post(&url)
            .set(
                "Content-Type",
                &format!("multipart/form-data; boundary={}", form_data.boundary()),
            )
            .send(form_data)?;

        let parsed_response: T2 = serde_json::from_reader(response.into_reader()).unwrap();

        Ok(parsed_response)
    }

mock:

        let server = MockServer::start();

        server.mock(|when, then| {
            when.method(POST).path(path);
            then.status(200).body(response);
        });
@alexliesenfeld
Copy link
Owner

alexliesenfeld commented Apr 18, 2021

Thanks for creating this issue. Multipart uploads are currently not supported but are far up on the todo list.

@ayrat555
Copy link
Author

Ok. Thanks. I think it should be mentioned somewhere.

I just tested my example with mockito. It works fine

@alexliesenfeld
Copy link
Owner

alexliesenfeld commented Apr 18, 2021

@ayrat555: You linked the Java version of mockito obove. Did you maybe mean the Rust mockito library? Because AFAICS, mockito (Rust) does not mention multipart support anywhere in the docs either.

I just tested your code locally, but it successfully ran through. Could you maybe provide a reproducable example with the problem you have?

My version is as follows:

#[test]
fn multipart_body_test() {
    #[derive(serde::Serialize, serde::Deserialize)]
    struct ExampleStruct {
        my_key: String,
    }

    // Arrange
    let server = MockServer::start();

    let mock = server.mock(|when, then| {
        when.method("POST").path("/hello");
        then.status(200).json_body_obj(&ExampleStruct{my_key: "my value".into()});
    });

    let path = get_test_data_path("tests/resources/static_yaml_mock.yaml");
    let res : Result<ExampleStruct, ureq::Error> = request_with_form_data(
        "hello",
        json!({ "my_key" : "my value" , "anotherKey": "some other value" }),
        "my_key",
        path,
        &server.base_url()
    );

    mock.assert();
    assert_eq!(res.is_ok(), true);
    assert_eq!(res.unwrap().my_key, "my value");
}

@ayrat555
Copy link
Author

ayrat555 commented Apr 18, 2021

You linked the Java version of mockito obove. Did you maybe mean the Rust mockito library? Because AFAICS, mockito (Rust) does not mention multipart support anywhere in the docs either.

Lol. you're right :)

Here's my examples:

alexliesenfeld added a commit that referenced this issue Apr 18, 2021
alexliesenfeld added a commit that referenced this issue Apr 18, 2021
@alexliesenfeld
Copy link
Owner

alexliesenfeld commented Apr 18, 2021

Should be fixed with PR #40 in v0.5.8. I have successfully tested your repo with it but please feel free to reopen this issue if it still fails on you for some reason.

@StarpTech
Copy link

StarpTech commented Dec 1, 2021

Hi, is it also possible to match binary content? body is from type String. It would be great to have a helper method when.body_from_file that reads a file from the file system. This would be congruent with then.body_from_file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants