mirror of
https://github.com/Dannecron/spring-boot-demo.git
synced 2025-12-25 16:22:35 +03:00
add neko controller
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
package com.github.dannecron.demo.http.controllers
|
||||
|
||||
import com.github.dannecron.demo.http.responses.neko.ImagesResponse
|
||||
import com.github.dannecron.demo.services.neko.Client
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = ["/api/neko"], produces = [MediaType.APPLICATION_JSON_VALUE])
|
||||
class NekoController(
|
||||
private val nekoClient: Client,
|
||||
) {
|
||||
@GetMapping("/categories")
|
||||
fun categories(): ResponseEntity<Any> = ResponseEntity(nekoClient.getCategories(), HttpStatus.OK)
|
||||
|
||||
@GetMapping("/images/{category}")
|
||||
fun images(
|
||||
@PathVariable category: String,
|
||||
@RequestParam imagesCount: Int = 1,
|
||||
): ResponseEntity<Any> = ResponseEntity(
|
||||
ImagesResponse(baseImages = nekoClient.getImages(category = category, amount = imagesCount)),
|
||||
HttpStatus.OK,
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.github.dannecron.demo.http.exceptions
|
||||
|
||||
import com.github.dannecron.demo.http.responses.BadRequestResponse
|
||||
import com.github.dannecron.demo.http.responses.BaseResponse
|
||||
import com.github.dannecron.demo.http.responses.NotFoundResponse
|
||||
import com.github.dannecron.demo.http.responses.UnprocessableResponse
|
||||
import org.springframework.http.HttpStatus
|
||||
@@ -42,4 +43,12 @@ class ExceptionHandler {
|
||||
UnprocessableResponse(exception.javaClass.name, exception.allErrors),
|
||||
HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
)
|
||||
|
||||
// 500
|
||||
@ExceptionHandler(RuntimeException::class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
fun handleUnexpectedRuntimeException(exception: RuntimeException): ResponseEntity<Any> = ResponseEntity(
|
||||
BaseResponse(com.github.dannecron.demo.http.responses.ResponseStatus.INTERNAL_ERROR),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,5 +6,6 @@ enum class ResponseStatus(@JsonValue val status: String) {
|
||||
OK("ok"),
|
||||
NOT_FOUND("not found"),
|
||||
BAD_REQUEST("bad request"),
|
||||
UNPROCESSABLE("unprocessable");
|
||||
UNPROCESSABLE("unprocessable"),
|
||||
INTERNAL_ERROR("internal");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.github.dannecron.demo.http.responses.neko
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Image(
|
||||
val url: String,
|
||||
val animeName: String?,
|
||||
val artistHref: String?,
|
||||
val artistName: String?,
|
||||
val sourceUrl: String?,
|
||||
) {
|
||||
fun isGif() = animeName != null
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.github.dannecron.demo.http.responses.neko
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import com.github.dannecron.demo.services.neko.dto.ImagesResponse as BaseResponse
|
||||
|
||||
@Serializable
|
||||
data class ImagesResponse(
|
||||
val images: List<Image>,
|
||||
) {
|
||||
constructor(baseImages: BaseResponse): this(
|
||||
images = baseImages.results.map {
|
||||
Image(it.url, it.animeName, it.artistHref, it.artistName, it.sourceUrl)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.github.dannecron.demo.http.controllers
|
||||
|
||||
import com.github.dannecron.demo.BaseUnitTest
|
||||
import com.github.dannecron.demo.services.neko.Client
|
||||
import com.github.dannecron.demo.services.neko.dto.Image
|
||||
import com.github.dannecron.demo.services.neko.dto.ImagesResponse
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.whenever
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
|
||||
import org.springframework.boot.test.mock.mockito.MockBean
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.get
|
||||
import kotlin.test.Test
|
||||
|
||||
@WebMvcTest(NekoController::class)
|
||||
class NekoControllerTest(
|
||||
@Autowired val mockMvc: MockMvc,
|
||||
): BaseUnitTest() {
|
||||
@MockBean
|
||||
private lateinit var nekoClient: Client
|
||||
|
||||
@Test
|
||||
fun categories_success() {
|
||||
whenever(nekoClient.getCategories()) doReturn setOf("cat1", "cat2")
|
||||
|
||||
mockMvc.get("/api/neko/categories")
|
||||
.andExpect { status { isOk() } }
|
||||
.andExpect { content { contentType(MediaType.APPLICATION_JSON) } }
|
||||
.andExpect { content { string("""["cat1","cat2"]""") } }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun images_success() {
|
||||
val category = "some"
|
||||
val animeName = "boku no pico"
|
||||
whenever(nekoClient.getImages(category = category, amount = 1)) doReturn ImagesResponse(
|
||||
results = listOf(
|
||||
Image(
|
||||
"http://localhost",
|
||||
animeName = animeName,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
mockMvc.get("/api/neko/images/$category")
|
||||
.andExpect { status { isOk() } }
|
||||
.andExpect { content { contentType(MediaType.APPLICATION_JSON) } }
|
||||
.andExpect { jsonPath("\$.images[0].animeName") { value(animeName) } }
|
||||
.andExpect { jsonPath("\$.images[0].artistName") { value(null) } }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user