diff --git a/src/main/kotlin/com/example/demo/AppConfig.kt b/src/main/kotlin/com/example/demo/AppConfig.kt index 4531089..ed9d098 100644 --- a/src/main/kotlin/com/example/demo/AppConfig.kt +++ b/src/main/kotlin/com/example/demo/AppConfig.kt @@ -4,8 +4,10 @@ import com.example.demo.provider.MockedShopProvider import com.example.demo.provider.ShopProvider import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration +import org.springframework.data.jpa.repository.config.EnableJpaRepositories @Configuration +@EnableJpaRepositories(basePackages = ["com.example.demo.providers"]) class AppConfig { @Bean fun shopProvider(): ShopProvider{ diff --git a/src/main/kotlin/com/example/demo/controllers/ProductController.kt b/src/main/kotlin/com/example/demo/controllers/ProductController.kt new file mode 100644 index 0000000..4d1f2aa --- /dev/null +++ b/src/main/kotlin/com/example/demo/controllers/ProductController.kt @@ -0,0 +1,25 @@ +package com.example.demo.controllers + +import com.example.demo.exceptions.NotFoundException +import com.example.demo.provider.ProductRepository +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.encodeToJsonElement +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.web.bind.annotation.* +import java.util.* + +@RestController +@RequestMapping(value = ["/api/product"]) +class ProductController( + @Autowired val productRepository: ProductRepository +) { + @GetMapping(value = ["{guid}"], produces = ["application/json"]) + @ResponseBody + fun getProduct( + @PathVariable guid: UUID + ): String { + val product = productRepository.findByGuid(guid = guid) ?: throw NotFoundException() + + return Json.encodeToJsonElement(value = product).toString() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/demo/provider/ProductRepository.kt b/src/main/kotlin/com/example/demo/provider/ProductRepository.kt new file mode 100644 index 0000000..992ef6a --- /dev/null +++ b/src/main/kotlin/com/example/demo/provider/ProductRepository.kt @@ -0,0 +1,13 @@ +package com.example.demo.provider + +import com.example.demo.models.Product +import org.springframework.data.jpa.repository.Query +import org.springframework.data.repository.CrudRepository +import org.springframework.stereotype.Repository +import java.util.* + +@Repository +interface ProductRepository: CrudRepository { + @Query(value = "SELECT * FROM Product WHERE guid = :guid") + fun findByGuid(guid: UUID): Product? +} \ No newline at end of file diff --git a/src/test/kotlin/com/example/demo/controllers/ProductControllerTest.kt b/src/test/kotlin/com/example/demo/controllers/ProductControllerTest.kt new file mode 100644 index 0000000..511f079 --- /dev/null +++ b/src/test/kotlin/com/example/demo/controllers/ProductControllerTest.kt @@ -0,0 +1,66 @@ +package com.example.demo.controllers + +import com.example.demo.models.Product +import com.example.demo.provider.ProductRepository +import com.example.demo.responses.ResponseStatus +import org.hamcrest.Matchers.nullValue +import org.junit.jupiter.api.Test +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.eq +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.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.get +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter +import java.util.* + +@WebMvcTest(ProductController::class) +class ProductControllerTest(@Autowired val mockMvc: MockMvc) { + @MockBean + private lateinit var productRepository: ProductRepository + + @Test + fun getProduct_success() { + val guid = UUID.randomUUID() + val now = OffsetDateTime.now() + val product = Product( + id = 12, + guid = guid, + name = "some", + description = null, + price = 11130, + createdAt = now, + updatedAt = null, + ) + + whenever(productRepository.findByGuid( + eq(guid), + )) doReturn product + + mockMvc.get("/api/product/$guid") + .andExpect { status { status { isOk() } } } + .andExpect { content { contentType("application/json") } } + .andExpect { jsonPath("\$.id") { value(product.id.toString()) } } + .andExpect { jsonPath("\$.guid") { value(guid.toString()) } } + .andExpect { jsonPath("\$.name") { value("some") } } + .andExpect { jsonPath("\$.createdAt") { value(now.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)) } } + .andExpect { jsonPath("\$.updatedAt") { value(nullValue()) } } + } + + @Test + fun getProduct_notFound() { + val guid = UUID.randomUUID() + + whenever(productRepository.findByGuid( + eq(guid), + )) doReturn null + + mockMvc.get("/api/product/$guid") + .andExpect { status { status { isNotFound() } } } + .andExpect { content { contentType("application/json") } } + .andExpect { jsonPath("\$.status") { value(ResponseStatus.NOT_FOUND.status) } } + } +} \ No newline at end of file