Tests for Apache HTTP client

This commit is contained in:
Kevin Grüneberg
2021-01-31 16:51:58 +01:00
parent 67a04d9b14
commit 14d71142fe
4 changed files with 122 additions and 5 deletions

View File

@@ -27,7 +27,7 @@ class PostgrestDefaultClient(
headers = headers,
schema = schema,
httpClient = PostgrestHttpClientApache(
postgrestJsonConverter = jsonConverter,
jsonConverter = jsonConverter,
httpClient = { HttpClients.createDefault() }
),
jsonConverter = jsonConverter

View File

@@ -48,7 +48,7 @@ class PostgrestQueryBuilder<T : Any>(url: URI, postgrestHttpClient: PostgrestHtt
fun insert(values: List<T>, upsert: Boolean = false, onConflict: String? = null, returning: Returning = Returning.REPRESENTATION, count: Count? = null): PostgrestFilterBuilder<T> {
setMethod(Method.POST)
val preferHeaders = mutableListOf<String>("return=${returning.identifier}")
val preferHeaders = mutableListOf("return=${returning.identifier}")
if (upsert) preferHeaders.add("resolution=merge-duplicates")
if (upsert && onConflict != null) setSearchParam("on_conflict", onConflict)

View File

@@ -3,7 +3,6 @@ package io.supabase.postgrest.http
import io.supabase.postgrest.json.PostgrestJsonConverter
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient
import org.apache.hc.client5.http.impl.classic.HttpClients
import org.apache.hc.core5.http.ClassicHttpResponse
import org.apache.hc.core5.http.HttpStatus
import org.apache.hc.core5.http.Method
@@ -19,14 +18,14 @@ import java.net.URI
*/
class PostgrestHttpClientApache(
private val httpClient: () -> CloseableHttpClient,
private val postgrestJsonConverter: PostgrestJsonConverter
private val jsonConverter: PostgrestJsonConverter
) : PostgrestHttpClient {
override fun execute(uri: URI, method: Method, headers: Map<String, String>, body: Any?): PostgrestHttpResponse {
return httpClient().use { httpClient ->
val httpRequest = HttpUriRequestBase(method.name, uri)
body?.apply {
val dataAsString = postgrestJsonConverter.serialize(body)
val dataAsString = jsonConverter.serialize(body)
httpRequest.entity = StringEntity(dataAsString)
}
headers.forEach { (name, value) -> httpRequest.addHeader(name, value) }

View File

@@ -0,0 +1,118 @@
package io.supabase.postgrest.http
import assertk.assertAll
import assertk.assertThat
import assertk.assertions.hasSize
import assertk.assertions.isEqualTo
import io.mockk.CapturingSlot
import io.mockk.every
import io.mockk.mockk
import io.mockk.slot
import io.supabase.postgrest.json.PostgrestJsonConverterJackson
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse
import org.apache.hc.core5.http.ClassicHttpRequest
import org.apache.hc.core5.http.Method
import org.apache.hc.core5.http.io.HttpClientResponseHandler
import org.apache.hc.core5.http.io.entity.StringEntity
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
import java.net.URI
import java.util.stream.Stream
internal class PostgrestHttpClientApacheTest {
private val uri = "https://test.com"
private val httpClientMock = mockk<CloseableHttpClient>()
private val postgrestHttpClient = PostgrestHttpClientApache(
httpClient = { httpClientMock },
jsonConverter = PostgrestJsonConverterJackson()
)
init {
every { httpClientMock.close() }.returns(Unit)
}
@Test
fun `should set http headers`() {
val httpResponse = mockk<CloseableHttpResponse>()
every { httpResponse.code } returns 200
every { httpResponse.entity } returns null
val requestCapture = mockHttpCallWithGetRequest(httpResponse)
val headers = mapOf("Authorization" to "foobar", "Content-Type" to "application/json")
postgrestHttpClient.execute(
method = Method.GET,
uri = URI(uri),
headers = headers
)
val request = requestCapture.captured
assertAll {
assertThat(request.headers).hasSize(headers.size)
headers.forEach { (name, value) ->
assertThat(request.getHeader(name).value).isEqualTo(value)
}
}
}
@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
inner class ThrowHttpException {
@ParameterizedTest
@MethodSource("exceptionTestData")
fun `should throw http exception when status is above 300`(testData: ExceptionTestData) {
val httpResponse = mockk<CloseableHttpResponse>()
val responseCode = testData.status
val httpBody = testData.body
every { httpResponse.code } returns responseCode
every { httpResponse.entity } returns httpBody?.let { StringEntity(it) }
mockHttpCallWithGetRequest(httpResponse)
val exception = assertThrows<PostgrestHttpException> {
postgrestHttpClient.execute(
method = Method.GET,
uri = URI(uri)
)
}
assertThat(exception.status).isEqualTo(responseCode)
assertThat(exception.data).isEqualTo(httpBody)
}
@Suppress("unused")
private fun exceptionTestData(): Stream<ExceptionTestData> {
return Stream.of(
ExceptionTestData(301, "httpbody"),
ExceptionTestData(301, null),
ExceptionTestData(400, "httpbody")
)
}
}
data class ExceptionTestData(
val status: Int,
val body: String?
)
private fun mockHttpCallWithGetRequest(httpResponse: CloseableHttpResponse): CapturingSlot<ClassicHttpRequest> {
val slot = slot<ClassicHttpRequest>()
every { httpClientMock.execute(capture(slot), any<HttpClientResponseHandler<Any>>()) }.answers {
val handler = args[1] as HttpClientResponseHandler<*>
handler.handleResponse(httpResponse)
}
return slot
}
}