add account not found exception

- update balance in AccountController with onErrorResume
- update AccountService
  - update getForUpdateById with switchIfEmpty
  - update getById with switchIfEmpty
- add AccountNotFoundException
This commit is contained in:
2025-09-11 18:49:16 +02:00
parent 25f534b6e3
commit e46bf55232
5 changed files with 56 additions and 6 deletions

View File

@@ -39,6 +39,6 @@ class AccountController(
@PathVariable account: UUID, @PathVariable account: UUID,
): Mono<Account.Response> = accountService.getById(account) ): Mono<Account.Response> = accountService.getById(account)
.map { it.toResponse() } .map { it.toResponse() }
.switchIfEmpty(Mono.error(ResponseStatusException(NOT_FOUND))) .onErrorResume { Mono.error(ResponseStatusException(NOT_FOUND)) }
.doOnError { log.debug { "account $account not found for balance" } } .doOnError { log.debug { "account $account not found for balance" } }
} }

View File

@@ -0,0 +1,10 @@
package ltd.lulz.exception
@Suppress("unused")
class AccountNotFoundException : RuntimeException {
constructor() : super()
constructor(message: String?) : super(message)
constructor(message: String?, cause: Throwable?) : super(message, cause)
constructor(cause: Throwable?) : super(cause)
}

View File

@@ -2,6 +2,7 @@ package ltd.lulz.service
import io.github.oshai.kotlinlogging.KotlinLogging import io.github.oshai.kotlinlogging.KotlinLogging
import java.util.UUID import java.util.UUID
import ltd.lulz.exception.AccountNotFoundException
import ltd.lulz.model.AccountEntity import ltd.lulz.model.AccountEntity
import ltd.lulz.repository.AccountRepository import ltd.lulz.repository.AccountRepository
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@@ -15,18 +16,28 @@ class AccountService(
private val accountRepository: AccountRepository, private val accountRepository: AccountRepository,
) { ) {
fun create(entity: AccountEntity): Mono<AccountEntity> = accountRepository fun create(
entity: AccountEntity,
): Mono<AccountEntity> = accountRepository
.save(entity) .save(entity)
.doOnNext { log.debug { "account created with id: ${it.id}" } } .doOnNext { log.debug { "account created with id: ${it.id}" } }
fun getById(id: UUID): Mono<AccountEntity> = accountRepository.findById(id) fun getById(
id: UUID,
): Mono<AccountEntity> = accountRepository.findById(id)
.doOnNext { log.debug { "found account by id: ${it.id}" } } .doOnNext { log.debug { "found account by id: ${it.id}" } }
.switchIfEmpty(Mono.error(AccountNotFoundException()))
@Transactional @Transactional
fun getForUpdateById(id: UUID): Mono<AccountEntity> = accountRepository.findByIdForUpdate(id) fun getForUpdateById(
id: UUID,
): Mono<AccountEntity> = accountRepository.findByIdForUpdate(id)
.doOnNext { log.trace { "account with id: ${it.id} locked for update" } } .doOnNext { log.trace { "account with id: ${it.id} locked for update" } }
.switchIfEmpty(Mono.error(AccountNotFoundException()))
@Transactional @Transactional
fun save(entity: AccountEntity): Mono<AccountEntity> = accountRepository.save(entity) fun save(
entity: AccountEntity,
): Mono<AccountEntity> = accountRepository.save(entity)
.doOnNext { log.trace { "account with id: ${it.id} saved" } } .doOnNext { log.trace { "account with id: ${it.id} saved" } }
} }

View File

@@ -4,6 +4,7 @@ import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import java.math.BigDecimal import java.math.BigDecimal
import java.util.UUID import java.util.UUID
import ltd.lulz.exception.AccountNotFoundException
import ltd.lulz.model.Account import ltd.lulz.model.Account
import ltd.lulz.model.AccountEntity import ltd.lulz.model.AccountEntity
import ltd.lulz.service.AccountService import ltd.lulz.service.AccountService
@@ -117,7 +118,7 @@ class AccountControllerTest {
@Test @Test
fun `account balance fail`() { fun `account balance fail`() {
// given // given
every { accountService.getById(any()) } returns Mono.empty() every { accountService.getById(any()) } returns Mono.error(AccountNotFoundException())
// when // when
val result = webTestClient.get() val result = webTestClient.get()

View File

@@ -6,6 +6,7 @@ import io.mockk.slot
import io.mockk.verify import io.mockk.verify
import java.math.BigDecimal import java.math.BigDecimal
import java.util.UUID import java.util.UUID
import ltd.lulz.exception.AccountNotFoundException
import ltd.lulz.model.AccountEntity import ltd.lulz.model.AccountEntity
import ltd.lulz.repository.AccountRepository import ltd.lulz.repository.AccountRepository
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
@@ -70,6 +71,19 @@ class AccountServiceTest {
verify { repository.findById(any(UUID::class)) } verify { repository.findById(any(UUID::class)) }
} }
@Test
fun `get by id - fail`() {
// given
every { repository.findById(any(UUID::class)) } returns Mono.empty()
// when stepped
StepVerifier.create(service.getById(uuid))
.expectError(AccountNotFoundException::class.java)
.verify()
verify { repository.findById(any(UUID::class)) }
}
@Test @Test
fun `get for update by id`() { fun `get for update by id`() {
// given // given
@@ -89,6 +103,20 @@ class AccountServiceTest {
verify { repository.findByIdForUpdate(any(UUID::class)) } verify { repository.findByIdForUpdate(any(UUID::class)) }
} }
@Test
fun `get for update by id - fail`() {
// given
every { repository.findByIdForUpdate(any(UUID::class)) } returns Mono.empty()
// when stepped
StepVerifier.create(service.getForUpdateById(uuid))
.expectError(AccountNotFoundException::class.java)
.verify()
verify { repository.findByIdForUpdate(any(UUID::class)) }
}
@Test @Test
fun `save change`() { fun `save change`() {
// given // given