오늘은 마지막 엔드포인트인 DELETE Endpoint를 만들어 봅시다.
Delete 테스트 함수를 만들어 줍니다.
@Nested
@DisplayName("DELETE /api/banks/{accountNumber}")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
inner class DeleteExistingBank {
@Test
fun `should delete the bank with the given account number`() {
// given
val accountNumber = 1234
// when
mockMvc.delete("$baseUrl/$accountNumber")
// then
.andDo { { print() } }
.andExpect {
status { isNoContent() }
}
}
}
@DeleteMapping("/{accountNumber}")
fun deleteBank(@PathVariable accountNumber: String): Unit {
}
BankController에 Delete맵핑을 해줍니다.
Unit을 반환한다는건 void(반환이 없음)을 의미합니다.
테스트를 실행해봅시다.

204가 아닌 200이 왔다고 합니다.
이전에 PostMapping을 진행할 때 처럼 ResponseStatus를 설정해 줍시다.
@DeleteMapping("/{accountNumber}")
@ResponseStatus(HttpStatus.NO_CONTENT)
fun deleteBank(@PathVariable accountNumber: String): Unit {
}
@Test
fun `should delete the bank with the given account number`() {
// given
val accountNumber = 1234
// when
mockMvc.delete("$baseUrl/$accountNumber")
// then
.andDo { { print() } }
.andExpect {
status { isNoContent() }
}
mockMvc.get("$baseUrl/$accountNumber")
.andExpect { status { isNotFound() } }
}
그리고 정말 데이터가 없는지를 확인하기 위해 테스트에 확인하는 mockMvc.get을 추가해줍니다.

실행했더니 404가 아닌 200이 왔다고 합니다.
이제 함수를 수정해 줍시다.
BankController
package com.study.hello_world.controller
import com.study.hello_world.model.Bank
import com.study.hello_world.service.BankService
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
@RestController
@RequestMapping("/api/banks")
class BankController(private val service: BankService) {
@ExceptionHandler(NoSuchElementException::class)
fun handleNotFound(e: NoSuchElementException): ResponseEntity<String> =
ResponseEntity(e.message, HttpStatus.NOT_FOUND)
@ExceptionHandler(IllegalArgumentException::class)
fun handleNotFound(e: IllegalArgumentException): ResponseEntity<String> =
ResponseEntity(e.message, HttpStatus.BAD_REQUEST)
@GetMapping
fun helloWorld(): Collection<Bank> = service.getBanks()
@GetMapping("/{accountNumber}")
fun getBBank(@PathVariable accountNumber: String) = service.getBank(accountNumber)
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun addBank(@RequestBody bank: Bank): Bank = service.addBank(bank)
@PatchMapping
fun updateBank(@RequestBody bank: Bank): Bank = service.updateBank(bank)
@DeleteMapping("/{accountNumber}")
@ResponseStatus(HttpStatus.NO_CONTENT)
fun deleteBank(@PathVariable accountNumber: String): Unit = service.deleteBank(accountNumber)
}
BankService
package com.study.hello_world.service
import com.study.hello_world.datasource.BankDataSource
import com.study.hello_world.model.Bank
import org.springframework.stereotype.Service
@Service
class BankService(private val dataSource: BankDataSource) {
fun getBanks(): Collection<Bank> {
return dataSource.retrieveBanks()
}
fun getBank(accountNumber: String): Bank = dataSource.retrieveBank(accountNumber)
fun addBank(bank: Bank): Bank = dataSource.createBank(bank)
fun updateBank(bank: Bank): Bank = dataSource.updateBank(bank)
fun deleteBank(accountNumber: String): Unit = dataSource.deleteBank(accountNumber)
}
BankDataSource
package com.study.hello_world.datasource
import com.study.hello_world.model.Bank
interface BankDataSource {
fun retrieveBanks(): Collection<Bank>
fun retrieveBank(accountNumber: String): Bank
fun createBank(bank: Bank): Bank
fun updateBank(bank: Bank): Bank
fun deleteBank(accountNumber: String)
}
MockBankDataSource
package com.study.hello_world.datasource.mock
import com.study.hello_world.datasource.BankDataSource
import com.study.hello_world.model.Bank
import org.springframework.stereotype.Repository
@Repository
class MockBankDataSource : BankDataSource {
val banks = mutableListOf(
Bank("1234", 3.14, 18),
Bank("110", 17.0, 0),
Bank("5678", 0.0, 100),
)
override fun retrieveBanks(): Collection<Bank> = banks
override fun retrieveBank(accountNumber: String): Bank =
banks.firstOrNull() { it.accountNumber == accountNumber }
?: throw NoSuchElementException("Could not find a bank with account number $accountNumber aaa")
override fun createBank(bank: Bank): Bank {
if (banks.any { it.accountNumber == bank.accountNumber }) {
throw IllegalArgumentException("Bank with account number ${bank.accountNumber} already exist")
}
banks.add(bank)
return bank
}
override fun updateBank(bank: Bank): Bank {
val currentBank = banks.firstOrNull { it.accountNumber == bank.accountNumber }
?: throw NoSuchElementException("Could not find a bank with account number $bank.accountNumber aaa")
banks.remove(currentBank)
banks.add(bank)
return bank
}
override fun deleteBank(accountNumber: String) {
val currentBank = banks.firstOrNull { it.accountNumber == accountNumber }
?: throw NoSuchElementException("Could not find a bank with account number $accountNumber aaa")
banks.remove(currentBank)
}
}
삭제하는 부분은 updateBank와 유사합니다.
새로운 계좌를 추가하는 부분과 return구문을 지워주시면 됩니다.
실행해 보시면 테스트를 성공적으로 통과하게 됩니다.

이번엔 없는 accountNumber를 주는 경우를 테스트 해 봅시다.
@Test
fun `should return NOT FOUND if no bank with given account number exists`() {
// given
val invalidAccountNumber = "does_not_exist"
// when
mockMvc.delete("$baseUrl/$invalidAccountNumber")
// then
.andDo { print() }
.andExpect { status { isNotFound() } }
}

728x90
'서버 > Kotlin-Spring_Boot' 카테고리의 다른 글
| JpaRepository SQLInsert ID column 순서 바뀜 주의... (0) | 2023.03.12 |
|---|---|
| QueryDsl jakarta 설정 방법 (0) | 2023.02.10 |
| Kotlin-Spring_Boot 강의 정리) 9. PATCH Endpoint (0) | 2023.02.02 |
| Kotlin-Spring_Boot 강의 정리) 8. POST Endpoint (1) | 2023.01.31 |
| Kotlin-Spring_Boot 강의 정리) 7. GET Single Bank (0) | 2023.01.30 |
댓글