Skip to content

Duplicate parts in generated snippets for multipart requests documented with MockMvc #746

@BeanVortex

Description

@BeanVortex

Hi.
I have this test method that documents multipart request:

    @Autowired
    private static final RestDocumentationContextProvider restDocumentation;
    private static MockMvc mockMvc;

    @BeforeEach
    void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                .apply(documentationConfiguration(restDocumentation))
                .alwaysDo(document("{method-name}"))
                .build();
    }

    @Test
    @Order(1)
    @WithMockUser(username = "anonymousUser")
    void signUpUser() throws Exception {
        var file1 = new MockMultipartFile("profileFile", "hello.jpg", MediaType.IMAGE_JPEG_VALUE,
                "Hello, World!".getBytes());
        var file2 = new MockMultipartFile("shopFile", "hello.jpg", MediaType.IMAGE_JPEG_VALUE,
                "Hello, World!".getBytes());
        var address = new MockPart("address", "address".getBytes());
        var des = new MockPart("description", "desc".getBytes());
        var username = new MockPart("userName", "user n".getBytes());
        var password = new MockPart("password", "pass1".getBytes());
        var passwordRepeat = new MockPart("passwordRepeat", "pass1".getBytes());
        var email = new MockPart("email", "email@mail.com".getBytes());
        MockPart[] parts = {email, des, username, address, passwordRepeat, password};
        mockMvc.perform(multipart("/api/user/signup/")
                .file(file1)
                .file(file2)
                .part(parts)
                .accept(MediaType.APPLICATION_JSON))
                .andDo(print())
                .andDo(result -> {
                    signupRefreshToken = result.getResponse().getHeader("refresh_token");
                    signupAccessToken = result.getResponse().getHeader("access_token");
                    JSONObject obj = new JSONObject(result.getResponse().getContentAsString());
                    userId = obj.getLong("id");
                    profileImage = obj.getString("profileImage");
                    shopImage = obj.getString("shopImage");

                })
                .andExpect(status().isOk())
                .andExpect(jsonPath("$").isMap())
                .andExpect(jsonPath("$.id").isNotEmpty())
        ;
    }
     

The generated curl document for this api is like this:

[source,bash]
----
$ curl 'http://localhost:8080/api/user/signup/' -i -X POST \
    -H 'Content-Type: multipart/form-data' \
    -H 'Accept: application/json' \
    -F 'email=email@mail.com' \
    -F 'description=desc' \
    -F 'userName=user n' \
    -F 'address=address' \
    -F 'passwordRepeat=pass1' \
    -F 'password=pass1' \
    -F 'profileFile=@hello.jpg;type=image/jpeg' \
    -F 'shopFile=@hello.jpg;type=image/jpeg' \
    -F 'email=email@mail.com' \
    -F 'description=desc' \
    -F 'userName=user n' \
    -F 'address=address' \
    -F 'passwordRepeat=pass1' \
    -F 'password=pass1'
----

so some of multipart fields are duplicated.
And also for http one:

[source,http,options="nowrap"]
----
POST /api/user/signup/ HTTP/1.1
Content-Type: multipart/form-data; boundary=6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Accept: application/json
Host: localhost:8080

--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=email

email@mail.com
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=description

desc
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=userName

user n
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=address

address
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=passwordRepeat

pass1
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=password

pass1
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=email

email@mail.com
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=description

desc
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=userName

user n
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=address

address
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=passwordRepeat

pass1
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=password

pass1
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=profileFile; filename=hello.jpg
Content-Type: image/jpeg

Hello, World!
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm
Content-Disposition: form-data; name=shopFile; filename=hello.jpg
Content-Type: image/jpeg

Hello, World!
--6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm--
----

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions