diff --git a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/build.gradle.kts b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/build.gradle.kts index 01fd5a6..8ae5a02 100644 --- a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/build.gradle.kts +++ b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/build.gradle.kts @@ -25,11 +25,15 @@ dependencies { implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + runtimeOnly("com.h2database:h2") runtimeOnly("mysql:mysql-connector-java") runtimeOnly("org.mariadb.jdbc:mariadb-java-client") + testImplementation("org.springframework.boot:spring-boot-starter-test") // testImplementation("org.springframework.security:spring-security-test") + testImplementation("io.mockk:mockk:1.12.3") + testImplementation("com.ninja-squad:springmockk:3.1.1") } tasks.withType { diff --git a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/main/kotlin/com/banjjoknim/playground/LearnWithMakingCleanArchitectureApplication.kt b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/main/kotlin/com/banjjoknim/playground/LearnWithMakingCleanArchitectureApplication.kt deleted file mode 100644 index d9a8be3..0000000 --- a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/main/kotlin/com/banjjoknim/playground/LearnWithMakingCleanArchitectureApplication.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.banjjoknim.playground - -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -class LearnWithMakingCleanArchitectureApplication - -fun main(args: Array) { - runApplication(*args) -} diff --git a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/in/web/ChangeNicknameWebAdapterTest.kt b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/in/web/ChangeNicknameWebAdapterTest.kt new file mode 100644 index 0000000..79861c1 --- /dev/null +++ b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/in/web/ChangeNicknameWebAdapterTest.kt @@ -0,0 +1,72 @@ +package com.banjjoknim.cleanarchitecture.user.adapter.`in`.web + +import com.banjjoknim.cleanarchitecture.user.application.port.`in`.ChangeNicknameResponseData +import com.banjjoknim.cleanarchitecture.user.application.port.`in`.ChangeNicknameUseCase +import com.fasterxml.jackson.databind.ObjectMapper +import com.ninjasquad.springmockk.MockkBean +import io.mockk.every +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest +import org.springframework.http.MediaType +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.post +import org.springframework.test.web.servlet.result.MockMvcResultHandlers +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.web.context.WebApplicationContext +import org.springframework.web.filter.CharacterEncodingFilter + +@WebMvcTest(ChangeNicknameWebAdapter::class) +class ChangeNicknameWebAdapterTest { + + @Autowired + private lateinit var mockmvc: MockMvc + + @Autowired + private lateinit var objectMapper: ObjectMapper + + @MockkBean + private lateinit var changeNicknameUseCase: ChangeNicknameUseCase + + @BeforeEach + fun setUp(webApplicationContext: WebApplicationContext) { + mockmvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) + .addFilter(CharacterEncodingFilter("UTF-8")) + .alwaysDo(MockMvcResultHandlers.print()) + .build() + } + + @DisplayName("닉네임 변경 테스트 케이스") + @Nested + inner class ChangeNicknameTestCases { + @Test + fun `닉네임을 변경한다`() { + every { changeNicknameUseCase.changeNickname(any()) } returns ChangeNicknameResponseData(1L) + val request = ChangeNicknameRequest(1L, "banjjoknim") + + mockmvc.post("/users") { + contentType = MediaType.APPLICATION_JSON + content = objectMapper.writeValueAsString(request) + }.andExpect { + content { json("""{"userId":1}""") } + status { isOk() } + } + } + + @Test + fun `잘못된 닉네임 변경 요청에 BadRequest 응답을 반환한다`() { + val request = ChangeNicknameRequest(1L, "banjjoknim!!") + + mockmvc.post("/users") { + contentType = MediaType.APPLICATION_JSON + content = objectMapper.writeValueAsString(request) + }.andExpect { + status { isBadRequest() } + } + } + } +} diff --git a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/out/persistence/LoadUserPersistenceAdapterTest.kt b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/out/persistence/LoadUserPersistenceAdapterTest.kt new file mode 100644 index 0000000..8ad8d1d --- /dev/null +++ b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/out/persistence/LoadUserPersistenceAdapterTest.kt @@ -0,0 +1,43 @@ +package com.banjjoknim.cleanarchitecture.user.adapter.out.persistence + +import com.banjjoknim.cleanarchitecture.user.pojo.Nickname +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.context.annotation.Import +import org.springframework.test.context.jdbc.Sql + +@DataJpaTest +@Import(value = [UserMapper::class, LoadUserPersistenceAdapter::class]) +class LoadUserPersistenceAdapterTest { + + @Autowired + private lateinit var loadUserPersistenceAdapter: LoadUserPersistenceAdapter + + @DisplayName("회원 조회 테스트 케이스") + @Nested + inner class LoadUserTestCases { + @Sql(statements = ["INSERT INTO USER VALUES (1, 'old')"]) + @Test + fun `회원이 존재하지 않을 경우 예외가 발생한다`() { + assertThrows("존재하지 않는 회원입니다. userId: 100") { + loadUserPersistenceAdapter.loadUser( + 100L + ) + } + } + + @Sql(statements = ["INSERT INTO USER VALUES (1, 'old')"]) + @Test + fun `회원이 존재할 경우 회원을 조회할 수 있다`() { + val user = loadUserPersistenceAdapter.loadUser(1L) + + Assertions.assertThat(user.id).isEqualTo(1) + Assertions.assertThat(user.nickname).isEqualTo(Nickname("old")) + } + } +} diff --git a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/out/persistence/UpsertUserPersistenceAdapterTest.kt b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/out/persistence/UpsertUserPersistenceAdapterTest.kt new file mode 100644 index 0000000..4c9cd66 --- /dev/null +++ b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/out/persistence/UpsertUserPersistenceAdapterTest.kt @@ -0,0 +1,39 @@ +package com.banjjoknim.cleanarchitecture.user.adapter.out.persistence + +import com.banjjoknim.cleanarchitecture.user.pojo.Nickname +import com.banjjoknim.cleanarchitecture.user.pojo.User +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.context.annotation.Import +import org.springframework.data.repository.findByIdOrNull +import org.springframework.test.context.jdbc.Sql + +@DataJpaTest +@Import(value = [UserMapper::class, UpsertUserPersistenceAdapter::class]) +class UpsertUserPersistenceAdapterTest { + + @Autowired + private lateinit var upsertUserPersistenceAdapter: UpsertUserPersistenceAdapter + + @Autowired + private lateinit var userEntityRepository: UserEntityRepository + + @DisplayName("회원 상태 저장 및 수정 테스트 케이스") + @Nested + inner class UpsertUserTestCases { + @Sql(statements = ["INSERT INTO USER VALUES (1, 'old')"]) + @Test + fun `회원 상태를 저장하거나 수정한다`() { + val updatedUser = User(1L, Nickname("new")) + + upsertUserPersistenceAdapter.upsertUser(updatedUser) + + val userEntity = userEntityRepository.findByIdOrNull(1L) + assertThat(userEntity?.nickname).isEqualTo(NicknameColumn("new")) + } + } +} diff --git a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/out/persistence/UserMapperTest.kt b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/out/persistence/UserMapperTest.kt new file mode 100644 index 0000000..d4c848e --- /dev/null +++ b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/adapter/out/persistence/UserMapperTest.kt @@ -0,0 +1,41 @@ +package com.banjjoknim.cleanarchitecture.user.adapter.out.persistence + +import com.banjjoknim.cleanarchitecture.user.pojo.Nickname +import com.banjjoknim.cleanarchitecture.user.pojo.User +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest + +@SpringBootTest(classes = [UserMapper::class]) +class UserMapperTest { + + @Autowired + private lateinit var userMapper: UserMapper + + @DisplayName("User POJO <-> User Entity 매핑 테스트 케이스") + @Nested + inner class UserMapperTestCases { + @Test + fun `User POJO 를 User Entity 로 변환한다`() { + val user = User(1L, Nickname("banjjoknim")) + + val userEntity = userMapper.mapToDomainEntity(user) + + assertThat(userEntity.id).isEqualTo(1) + assertThat(userEntity.nickname).isEqualTo(NicknameColumn("banjjoknim")) + } + + @Test + fun `User Entity 를 User POJO 로 변환한다`() { + val userEntity = UserEntity(1L, NicknameColumn("banjjoknim")) + + val user = userMapper.mapToDomainModel(userEntity) + + assertThat(user.id).isEqualTo(1) + assertThat(user.nickname).isEqualTo(Nickname("banjjoknim")) + } + } +} diff --git a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/application/service/ChangeNicknameServiceTest.kt b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/application/service/ChangeNicknameServiceTest.kt new file mode 100644 index 0000000..e8d7f49 --- /dev/null +++ b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/application/service/ChangeNicknameServiceTest.kt @@ -0,0 +1,46 @@ +package com.banjjoknim.cleanarchitecture.user.application.service + +import com.banjjoknim.cleanarchitecture.user.application.port.`in`.ChangeNicknameRequestData +import com.banjjoknim.cleanarchitecture.user.application.port.out.LoadUserPersistencePort +import com.banjjoknim.cleanarchitecture.user.application.port.out.UpsertUserPersistencePort +import com.banjjoknim.cleanarchitecture.user.pojo.Nickname +import com.banjjoknim.cleanarchitecture.user.pojo.User +import io.mockk.Runs +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +class ChangeNicknameServiceTest { + + private val loadUserPersistencePort = mockk() + private val upsertUserPersistencePort = mockk() + private val changeNicknameService = ChangeNicknameService(loadUserPersistencePort, upsertUserPersistencePort) + + @DisplayName("닉네임 변경 테스트 케이스") + @Nested + inner class ChangeNicknameTestCases { + + private lateinit var testUser: User + private val testChangeNicknameRequestData = ChangeNicknameRequestData(1L, "new") + + @BeforeEach + fun setUp() { + testUser = User(1L, Nickname("old")) + } + + @Test + fun `닉네임을 변경한다`() { + every { loadUserPersistencePort.loadUser(any()) } returns testUser + every { upsertUserPersistencePort.upsertUser(any()) } just Runs + + changeNicknameService.changeNickname(testChangeNicknameRequestData) + + assertThat(testUser.nickname).isEqualTo(Nickname("new")) + } + } +} diff --git a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/pojo/UserTest.kt b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/pojo/UserTest.kt index 64d96e2..88421f6 100644 --- a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/pojo/UserTest.kt +++ b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/cleanarchitecture/user/pojo/UserTest.kt @@ -7,7 +7,8 @@ import org.junit.jupiter.api.Test class UserTest { - @DisplayName("회원 이름 변경 테스트 케이스") + + @DisplayName("회원 닉네임 변경 테스트 케이스") @Nested inner class ChangeNicknameTestCases { @Test diff --git a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/playground/LearnWithMakingCleanArchitectureApplicationTests.kt b/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/playground/LearnWithMakingCleanArchitectureApplicationTests.kt deleted file mode 100644 index 46da497..0000000 --- a/놀이터(예제 코드 작성)/learn-with-making-clean-architecture/src/test/kotlin/com/banjjoknim/playground/LearnWithMakingCleanArchitectureApplicationTests.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.banjjoknim.playground - -import org.junit.jupiter.api.Test -import org.springframework.boot.test.context.SpringBootTest - -@SpringBootTest -class LearnWithMakingCleanArchitectureApplicationTests { - - @Test - fun contextLoads() { - } - -}