diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5c90857 Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index 4f1386b..fc25173 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,4 @@ ### 필요한건 Notion에 저장해놓을게요 양해부탁드려요.. https://www.notion.so/kkw01234/dbaf7c5999e04a39b8241682854ddfae -### 권한 요청 필요합니다 +### 권한 요청 필요합니다 \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 9a7cabb..ae78695 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,7 @@ plugins { id("io.spring.dependency-management") version "1.0.9.RELEASE" kotlin("jvm") version "1.3.72" kotlin("plugin.spring") version "1.3.72" + kotlin("plugin.jpa") version "1.3.72" } group = "com.example" @@ -17,9 +18,13 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-web") + implementation ("org.springframework.boot:spring-boot-starter-aop") + implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + runtimeOnly("mysql:mysql-connector-java") + testImplementation("com.h2database:h2") testImplementation("org.springframework.boot:spring-boot-starter-test") { exclude(group = "org.junit.vintage", module = "junit-vintage-engine") } diff --git a/src/main/kotlin/com/example/kotlinweb/KotlinwebApplication.kt b/src/main/kotlin/com/example/kotlinweb/KotlinwebApplication.kt index 326f1e6..7785c0d 100644 --- a/src/main/kotlin/com/example/kotlinweb/KotlinwebApplication.kt +++ b/src/main/kotlin/com/example/kotlinweb/KotlinwebApplication.kt @@ -2,10 +2,12 @@ package com.example.kotlinweb import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication +import org.springframework.context.annotation.EnableAspectJAutoProxy +@EnableAspectJAutoProxy @SpringBootApplication class KotlinwebApplication fun main(args: Array) { runApplication(*args) -} +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/aspect/BoardAspect.kt b/src/main/kotlin/com/example/kotlinweb/aspect/BoardAspect.kt new file mode 100644 index 0000000..1358ab6 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/aspect/BoardAspect.kt @@ -0,0 +1,27 @@ +package com.example.kotlinweb.aspect + +import com.example.kotlinweb.model.Board +import org.aspectj.lang.JoinPoint +import org.aspectj.lang.ProceedingJoinPoint +import org.aspectj.lang.annotation.Aspect +import org.aspectj.lang.annotation.Before +import org.aspectj.lang.annotation.Pointcut +import org.springframework.stereotype.Component + + +@Aspect +@Component +class BoardAspect( + private val boardList: MutableList +){ + + @Before(value = "execution(* com.example.kotlinweb.service.BoardService.*(..)) && args(id))") + fun interceptBoard(joinPoint: JoinPoint, id:Int){ + if(id <= 0) throw RuntimeException("1이상의 숫자를 입력해주세요") + if(id > boardList.size ) throw RuntimeException("게시글 개수보다 많습니다.") + } + + + + +} diff --git a/src/main/kotlin/com/example/kotlinweb/config/BoardConfig.kt b/src/main/kotlin/com/example/kotlinweb/config/BoardConfig.kt new file mode 100644 index 0000000..eb03d94 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/config/BoardConfig.kt @@ -0,0 +1,16 @@ +package com.example.kotlinweb.config + +import com.example.kotlinweb.model.Board +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class BoardConfig{ + + + @Bean + fun boardList():MutableList{ + return mutableListOf(); + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/config/WebConfig.kt b/src/main/kotlin/com/example/kotlinweb/config/WebConfig.kt new file mode 100644 index 0000000..81202f8 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/config/WebConfig.kt @@ -0,0 +1,35 @@ +package com.example.kotlinweb.config + +import com.example.kotlinweb.interceptor.TokenInterceptor +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.web.filter.CharacterEncodingFilter +import org.springframework.web.servlet.config.annotation.CorsRegistry +import org.springframework.web.servlet.config.annotation.InterceptorRegistry +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer + +@Configuration +class WebConfig( + private val tokenInterceptor: TokenInterceptor +): WebMvcConfigurer { + + override fun addCorsMappings(registry: CorsRegistry) { + registry.addMapping("/**") + .allowedMethods("GET", "PUT", "DELETE", "POST", "OPTIONS") + .allowedOrigins("*") + .allowedHeaders("*") + .allowCredentials(true) + } + + @Bean + fun characterEncodingFilter(): CharacterEncodingFilter { + val characterEncodingFilter: CharacterEncodingFilter = CharacterEncodingFilter() + characterEncodingFilter.encoding = "UTF-8" + characterEncodingFilter.setForceEncoding(true) + return characterEncodingFilter + } + + override fun addInterceptors(registry: InterceptorRegistry) { + registry.addInterceptor(tokenInterceptor).addPathPatterns("/**") + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/controller/BoardController.kt b/src/main/kotlin/com/example/kotlinweb/controller/BoardController.kt new file mode 100644 index 0000000..b90da00 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/controller/BoardController.kt @@ -0,0 +1,39 @@ +package com.example.kotlinweb.controller + +import com.example.kotlinweb.model.Board +import com.example.kotlinweb.model.request.BoardRequest +import com.example.kotlinweb.model.response.Response +import com.example.kotlinweb.service.BoardService +import org.springframework.http.HttpStatus +import org.springframework.web.bind.annotation.* + +@RestController +class BoardController( + private val boardService: BoardService +){ + + @PostMapping("/board") + fun postBoard(@RequestBody boardRequest:BoardRequest): Response { + return Response(HttpStatus.CREATED, "create", boardService.createBoard(boardRequest)); + } + + @GetMapping("/board") + fun findAllBoard(): Response> { + return Response(HttpStatus.OK, "findAll", boardService.findAllBoard()) + } + + @GetMapping("/board/{id}") + fun findBoard(@PathVariable id:Long): Response { + return Response(HttpStatus.OK, "find", boardService.findBoard(id)) + } + + @DeleteMapping("/board/{id}") + fun deleteBoard(@PathVariable id:Long): Response { + return Response(HttpStatus.OK, "delete", boardService.deleteBoard(id)) + } + + @PutMapping("/board/{id}") + fun update(@PathVariable id:Long, @RequestBody boardRequest:BoardRequest): Response { + return Response(HttpStatus.OK, "update", boardService.updateBoard(id, boardRequest)) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/controller/HealthController.kt b/src/main/kotlin/com/example/kotlinweb/controller/HealthController.kt index fed3266..d0bdd04 100644 --- a/src/main/kotlin/com/example/kotlinweb/controller/HealthController.kt +++ b/src/main/kotlin/com/example/kotlinweb/controller/HealthController.kt @@ -13,5 +13,5 @@ class HealthController{ @get:GetMapping(value = ["/health_check.html"]) val ratingStatus: ResponseEntity get() = ResponseEntity("Health", HttpStatus.OK) - + } diff --git a/src/main/kotlin/com/example/kotlinweb/controller/UserController.kt b/src/main/kotlin/com/example/kotlinweb/controller/UserController.kt new file mode 100644 index 0000000..64cc0a9 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/controller/UserController.kt @@ -0,0 +1,7 @@ +package com.example.kotlinweb.controller + +class UserController( + +){ + +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/exception/ControllerAdvice.kt b/src/main/kotlin/com/example/kotlinweb/exception/ControllerAdvice.kt new file mode 100644 index 0000000..2e697bd --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/exception/ControllerAdvice.kt @@ -0,0 +1,32 @@ +package com.example.kotlinweb.exception + +import com.example.kotlinweb.model.response.Response +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.ControllerAdvice +import org.springframework.web.bind.annotation.ExceptionHandler +import org.springframework.web.client.HttpClientErrorException + +@ControllerAdvice +class ControllerAdvice(){ + + @ExceptionHandler(Exception::class) + private fun handleUnexpectedHandler(exception: Exception): ResponseEntity> { + return makeResponseException(exception) + } + + private fun makeResponseException(exception: Exception): ResponseEntity>{ + return when(exception){ + is HttpClientErrorException.BadRequest ->{ + makeResponse(exception.message, HttpStatus.BAD_REQUEST) + } + else -> { + makeResponse(exception.message,HttpStatus.INTERNAL_SERVER_ERROR) + } + } + } + private fun makeResponse(message:String?, status:HttpStatus, data:Any? = null):ResponseEntity>{ + return ResponseEntity(Response(code = status, message = message?.let { message } + ?: "", data = data), status) + } +} diff --git a/src/main/kotlin/com/example/kotlinweb/interceptor/TokenInterceptor.kt b/src/main/kotlin/com/example/kotlinweb/interceptor/TokenInterceptor.kt new file mode 100644 index 0000000..552b412 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/interceptor/TokenInterceptor.kt @@ -0,0 +1,34 @@ +package com.example.kotlinweb.interceptor + +import com.example.kotlinweb.model.UserContext +import com.example.kotlinweb.service.UserService +import org.springframework.stereotype.Component +import org.springframework.web.servlet.ModelAndView +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter +import java.lang.RuntimeException +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + +@Component +class TokenInterceptor( + private val userService: UserService +): HandlerInterceptorAdapter(){ + @Throws(Exception::class) + override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { + val headerMap: MutableMap = HashMap() + request.headerNames.toList().map { headerMap[it.toLowerCase()] = request.getHeader(it) } + + val token = headerMap["authorization"] ?: throw RuntimeException("not found authorization token") + + val user = userService.getUserByToken(token) + UserContext.setUser(user) + + return super.preHandle(request, response, handler) + } + + @Throws(Exception::class) + override fun postHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any, modelAndView: ModelAndView?) { + UserContext.removeAll() + super.postHandle(request, response, handler, modelAndView) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/model/Board.kt b/src/main/kotlin/com/example/kotlinweb/model/Board.kt new file mode 100644 index 0000000..9c7a489 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/model/Board.kt @@ -0,0 +1,15 @@ +package com.example.kotlinweb.model + +import javax.persistence.* + +@Entity +class Board( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + val id:Long? = null, + var title:String, + var content:String, + @ManyToOne + @JoinColumn(name = "userId") + val user:User +) \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/model/User.kt b/src/main/kotlin/com/example/kotlinweb/model/User.kt new file mode 100644 index 0000000..984b7fa --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/model/User.kt @@ -0,0 +1,15 @@ +package com.example.kotlinweb.model + +import javax.persistence.Entity +import javax.persistence.GeneratedValue +import javax.persistence.GenerationType +import javax.persistence.Id + +@Entity +class User( + @Id + val id: String, + val password: String, + val name: String, + var token: String? = null +) \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/model/UserContext.kt b/src/main/kotlin/com/example/kotlinweb/model/UserContext.kt new file mode 100644 index 0000000..16f5784 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/model/UserContext.kt @@ -0,0 +1,20 @@ +package com.example.kotlinweb.model + +object UserContext{ + + private val exception = ThreadLocal() + private val user = ThreadLocal() + + fun setUser(user:User) = this.user.set(user) + + fun getUser() = this.user.get() + + fun removeUser() = user.remove() + + fun removeException() = exception.remove() + + fun removeAll() { + removeUser() + removeException() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/model/request/BoardRequest.kt b/src/main/kotlin/com/example/kotlinweb/model/request/BoardRequest.kt new file mode 100644 index 0000000..98f7ef1 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/model/request/BoardRequest.kt @@ -0,0 +1,6 @@ +package com.example.kotlinweb.model.request + +class BoardRequest( + val title:String, + val content:String +) \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/model/response/Response.kt b/src/main/kotlin/com/example/kotlinweb/model/response/Response.kt new file mode 100644 index 0000000..4bec0b4 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/model/response/Response.kt @@ -0,0 +1,9 @@ +package com.example.kotlinweb.model.response + +import org.springframework.http.HttpStatus + +class Response( + val code:HttpStatus, + val message:String, + val data: T +) \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/repository/BoardRepository.kt b/src/main/kotlin/com/example/kotlinweb/repository/BoardRepository.kt new file mode 100644 index 0000000..8418cfa --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/repository/BoardRepository.kt @@ -0,0 +1,6 @@ +package com.example.kotlinweb.repository + +import com.example.kotlinweb.model.Board +import org.springframework.data.jpa.repository.JpaRepository + +interface BoardRepository: JpaRepository{} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/repository/UserRepository.kt b/src/main/kotlin/com/example/kotlinweb/repository/UserRepository.kt new file mode 100644 index 0000000..9db3ed4 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/repository/UserRepository.kt @@ -0,0 +1,8 @@ +package com.example.kotlinweb.repository + +import com.example.kotlinweb.model.User +import org.springframework.data.jpa.repository.JpaRepository + +interface UserRepository: JpaRepository{ + fun findByToken(token:String):User? +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/service/BoardService.kt b/src/main/kotlin/com/example/kotlinweb/service/BoardService.kt new file mode 100644 index 0000000..a03df18 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/service/BoardService.kt @@ -0,0 +1,43 @@ +package com.example.kotlinweb.service + +import com.example.kotlinweb.model.Board +import com.example.kotlinweb.model.UserContext +import com.example.kotlinweb.model.request.BoardRequest +import com.example.kotlinweb.repository.BoardRepository +import com.example.kotlinweb.repository.UserRepository +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import java.lang.RuntimeException +import javax.transaction.Transactional + +@Service +class BoardService( + private val boardRepository: BoardRepository +){ + + fun createBoard(boardRequest:BoardRequest):Board{ + val board = Board(null, boardRequest.title, boardRequest.content, UserContext.getUser()) + return boardRepository.save(board) + } + + fun findBoard(id:Long):Board{ + return boardRepository.findByIdOrNull(id) ?: throw RuntimeException("not found board") + } + fun findAllBoard():List{ + return boardRepository.findAll() + } + + fun deleteBoard(id:Long):Boolean{ + boardRepository.deleteById(id) + return true + } + + @Transactional + fun updateBoard(id:Long, boardRequest: BoardRequest):Board{ + val board = boardRepository.findByIdOrNull(id) ?: throw RuntimeException("not found board") + board.title = boardRequest.title + board.content = boardRequest.content + return board + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/example/kotlinweb/service/UserService.kt b/src/main/kotlin/com/example/kotlinweb/service/UserService.kt new file mode 100644 index 0000000..4c9b018 --- /dev/null +++ b/src/main/kotlin/com/example/kotlinweb/service/UserService.kt @@ -0,0 +1,40 @@ +package com.example.kotlinweb.service + +import com.example.kotlinweb.model.User +import com.example.kotlinweb.repository.UserRepository +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import java.lang.RuntimeException +import java.time.ZonedDateTime +import kotlin.random.Random + +@Service +class UserService( + private val userRepository: UserRepository +){ + + fun login(id: String, password: String):User{ + val user = findUser(id) + if(user.password != password) throw RuntimeException("not found user") + user.token = Random(ZonedDateTime.now().toInstant().toEpochMilli()).nextBits(12).toString() + return user + } + + fun logout(id: String):User{ + val user =findUser(id) + user.token = null + return user + } + + fun register(user: User){ + userRepository.save(user) + } + + fun getUserByToken(token:String):User{ + return userRepository.findByToken(token) ?: throw RuntimeException("not found user"); + } + + private fun findUser(id:String):User{ + return userRepository.findByIdOrNull(id) ?: throw RuntimeException("not found user") + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8b13789..1a263cf 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,8 @@ - +spring.datasource.url=jdbc:mysql://localhost:3307/board-study?useSSL=false&characterEncoding=utf-8 +spring.datasource.username=root +spring.datasource.password=1234 +spring.datasource.driverClassName=com.mysql.jdbc.Driver +spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.show-sql=true +spring.jpa.database=mysql \ No newline at end of file diff --git a/src/test/kotlin/com/example/kotlinweb/controller/BoardControllerTest.kt b/src/test/kotlin/com/example/kotlinweb/controller/BoardControllerTest.kt new file mode 100644 index 0000000..ce11eb5 --- /dev/null +++ b/src/test/kotlin/com/example/kotlinweb/controller/BoardControllerTest.kt @@ -0,0 +1,115 @@ +package com.example.kotlinweb.controller + +import com.example.kotlinweb.model.Board +import com.example.kotlinweb.model.User +import com.example.kotlinweb.model.response.Response +import com.example.kotlinweb.repository.UserRepository +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import org.junit.jupiter.api.* +import org.junit.jupiter.api.Assertions.assertEquals +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.http.MediaType +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders +import org.springframework.test.web.servlet.result.MockMvcResultMatchers + + +@SpringBootTest +@AutoConfigureMockMvc +@ActiveProfiles(value = ["test"]) +@TestMethodOrder(MethodOrderer.OrderAnnotation::class) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class BoardControllerTest { + + + @Autowired + private lateinit var mockMvc:MockMvc + + @Autowired + private lateinit var userRepository: UserRepository + + companion object{ + + private val objectMapper:ObjectMapper = jacksonObjectMapper() + private val user = User("123","123","123","123") + } + + @BeforeAll + fun init(){ + userRepository.save(user) + } + + + @Test + @Order(1) + fun createBoard(){ + val board = Board(null,"abcd","abcd",user) + val result = mockMvc.perform(MockMvcRequestBuilders.post("/board") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(board)) + .header("Authorization","123")) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + val resultPayload = objectMapper.readValue(result.response.contentAsString, object : TypeReference>(){}) + assertEquals(resultPayload.data.title, board.title) + assertEquals(resultPayload.data.content, board.content) + } + @Test + @Order(2) + fun findBoard(){ + val board = Board(null,"abcd","abcd",user) + val result = mockMvc.perform(MockMvcRequestBuilders.get("/board/1") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization","123")) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + val resultPayload = objectMapper.readValue(result.response.contentAsString, object : TypeReference>(){}) + assertEquals(resultPayload.data.title, board.title) + assertEquals(resultPayload.data.content, board.content) + } + + @Test + @Order(3) + fun findAllBoard(){ + val result = mockMvc.perform(MockMvcRequestBuilders.get("/board") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization","123")) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + val resultPayload = objectMapper.readValue(result.response.contentAsString, object : TypeReference>>(){}) + assertEquals(resultPayload.data.size, 1) + } + + @Test + @Order(4) + fun updateBoard(){ + val board = Board(null,"abcd","abcd",user) + val result = mockMvc.perform(MockMvcRequestBuilders.put("/board/1") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(board)) + .header("Authorization","123")) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + val resultPayload = objectMapper.readValue(result.response.contentAsString, object : TypeReference>(){}) + assertEquals(resultPayload.data.title, board.title) + assertEquals(resultPayload.data.content, board.content) + } + + @Test + @Order(5) + fun deleteBoard(){ + val result = mockMvc.perform(MockMvcRequestBuilders.delete("/board/1") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization","123")) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn() + val resultPayload = objectMapper.readValue(result.response.contentAsString, object : TypeReference>(){}) + assertEquals(resultPayload.data, true) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/com/example/kotlinweb/service/BoardServiceTest.kt b/src/test/kotlin/com/example/kotlinweb/service/BoardServiceTest.kt new file mode 100644 index 0000000..54bf5b0 --- /dev/null +++ b/src/test/kotlin/com/example/kotlinweb/service/BoardServiceTest.kt @@ -0,0 +1,10 @@ +package com.example.kotlinweb.service + +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ActiveProfiles + +@SpringBootTest +@ActiveProfiles(value = ["test"]) +class BoardServiceTest{ + // TODO: 만들어야함 +} \ No newline at end of file diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..6e44c54 --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,12 @@ +spring.profiles.active=test +spring.datasource.url=jdbc:h2:mem:default;mode=mysql +spring.datasource.driverClassName=org.h2.Driver + +spring.datasource.username=sa +spring.datasource.password= + +spring.jpa.database=h2 +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.show-sql=true +#spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl +spring.jpa.generate-ddl=true \ No newline at end of file