(x-опубликовано в личном блоге здесь )
Фон
В течение последнего года или около того я активно работал с spring, особенно с spring webflux; создавал масштабируемые реактивные микросервисы для наших клиентов.
Исходя из spring MVC, изучение веб-потока и привыкание к реактивному программированию в целом было отличным и достойным опытом обучения, и я настоятельно рекомендую ознакомиться с разделом “Ссылки”, если вы не слышали о реактивном программировании и/или подумывали о том, чтобы попробовать и не знаете, с чего начать. Но, по сути, реактивное программирование включает в себя модель создания, запроса и манипулирования данными контролируемым (с точки зрения потребителей) и неблокирующим способом.
Клиент веб-тестирования представляет собой http-клиент высокого уровня для реактивного тестирования с плавными проверками, упакованный в spring web flux. Недавно, во время интеграционного тестирования приложения, которое принимало данные как составные/данные формы Мне нужно было выяснить, как эффективно протестировать данные с помощью webtestclient, и лично я обнаружил отсутствие исчерпывающих ресурсов в Интернете, поэтому я написал этот пост в блоге, чтобы поделиться своими собственными знаниями.
Тестирование веб-форм с помощью Web flux
Давайте предположим, что мы пытаемся отправить запрос на заполнение формы api, которая принимает документ (изображение, текст, обычный двоичный файл и т.д.) И некоторые текстовые данные.
Чтобы помочь в нашем примере, давайте представим, что форма представляет собой настройку профиля для службы общего доступа к документам и принимает следующие входные данные:
- Изображение профиля ( метка api: изображение профиля )
- Имя пользователя ( метка api: имя пользователя )
- Электронная почта ( метка api: электронная почта )
- PDF-документ для совместного использования ( метка api: пользовательский документ )
Чтобы начать отправку данных, мы будем использовать библиотеку spring под названием Multipart Body Builder , которая предоставляет удобный api для настройки тела для составных запросов.
Чтобы отправить первую часть, изображение профиля, мы можем настроить его как:
val bodyBuilder = MultipartBodyBuilder() bodyBuilder.part("profileImage", ClassPathResource("test-image.jpg").file.readBytes()).header("Content-Disposition", "form-data; name=profileImage; filename=profile-image.jpg")
Чтобы немного объяснить, что там происходит, мы просто говорим культуристу загрузить изображение, найденное в папке src/test/resources
с именем test-image.jpg
как часть изображения профиля этого тела. Настоящим преимуществом здесь является настройка части Заголовок , поскольку это то, что используется внутренними компонентами клиента веб-тестирования (в частности, библиотекой Synchronoss-nio , которую webflux использует внутри) для определения типа отправляемых данных формы и способа их обработки.
Также обратите внимание, что реальное имя файла, которое будет загружено на веб-сервер, получающий запрос, – это profile-image.jpg
имя файла, которое отправляется как часть заголовков,.
Аналогично изображению профиля, мы также можем отправить документ как часть всей полезной нагрузки запроса:
bodyBuilder.part("userDocument", ClassPathResource("user-document.pdf").file.readBytes()).header("Content-Disposition", "form-data; name=userDocument; filename=my-thesis.pdf")
Аналогично предыдущей полезной нагрузке, мы тестируем bodybuilder 💪 , чтобы прочитать файл в папке test resources под названием user-document.pdf
в виде байтов и отправить документ с именем my-thesis.pdf
в веб-api формы.
Как вы уже можете видеть, по сравнению с некоторыми другими способами сделать это, например, в этом превосходном блоге , использование MultipartBodyBuilder довольно удобно.
Теперь для последних двух оставшихся частей api форм, которые обычно представляют собой только обычный текст, мы можем настроить их следующим образом:
bodyBuilder.part("username", "shiveenpandita", MediaType.TEXT_PLAIN).header("Content-Disposition", "form-data; name=username").header("Content-type", "text/plain") bodyBuilder.part("email", "shiveenpandita@gmail.com", MediaType.TEXT_PLAIN).header("Content-Disposition", "form-data; name=email").header("Content-type", "text/plain")
У-у-у! 🎉 Теперь мы подключили все поля нашей формы.
Теперь, чтобы увидеть все это в действии и собрать все вместе, мы можем просто настроить интеграционный тест spring и использовать наш недавно настроенный body builder в качестве:
@RunWith(SpringRunner::class.java) @SpringBootTest @AutoConfigureWebTestClient class WebClientTest { private lateinit var webclient: WebTestClient @Test fun `test webform api`() { val bodyBuilder = MultipartBodyBuilder() bodyBuilder.part("profileImage", ClassPathResource("test-image.jpg").file.readBytes()).header("Content-Disposition", "form-data; name=profileImage; filename=profile-image.jpg") bodyBuilder.part("userDocument", ClassPathResource("test-document.pdf").file.readBytes()).header("Content-Disposition", "form-data; name=userDocument; filename=my-thesis.pdf") bodyBuilder.part("username", "shiveenpandita", MediaType.TEXT_PLAIN).header("Content-Disposition", "form-data; name=username").header("Content-type", "text/plain") bodyBuilder.part("email", "shiveenpandita@gmail.com", MediaType.TEXT_PLAIN).header("Content-Disposition", "form-data; name=email").header("Content-type", "text/plain") webClient.post() .uri("/v1/test-api") .contentType(MediaType.MULTIPART_FORM_DATA) .body(BodyInserters.fromMultipartData(bodyBuilder.build())) .exchange() .expectStatus().isOk } }
Приведенный выше фрагмент кода успешно отправит необходимые данные в наш rest api, и клиент веб-тестирования подтвердит, что ответ 200 в порядке.
Рекомендации
Оригинал: “https://dev.to/shavz/sending-multipart-form-data-using-spring-webtestclient-2gb7”