├── .github ├── ISSUE_TEMPLATE │ └── 📚-study.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── Eunji ├── h2 │ ├── .gitignore │ ├── build.gradle.kts │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle.kts │ └── src │ │ ├── main │ │ ├── java │ │ │ └── org │ │ │ │ └── example │ │ │ │ └── demo │ │ │ │ ├── Main.java │ │ │ │ ├── controller │ │ │ │ ├── ExceptionControllerAdvice.java │ │ │ │ ├── HealthCheckController.java │ │ │ │ ├── PostController.java │ │ │ │ ├── PostCreateController.java │ │ │ │ ├── UserController.java │ │ │ │ └── UserCreateController.java │ │ │ │ ├── exception │ │ │ │ ├── CertificationCodeNotMatchedException.java │ │ │ │ └── ResourceNotFoundException.java │ │ │ │ ├── model │ │ │ │ ├── UserStatus.java │ │ │ │ └── dto │ │ │ │ │ ├── MyProfileResponse.java │ │ │ │ │ ├── PostCreateDto.java │ │ │ │ │ ├── PostResponse.java │ │ │ │ │ ├── PostUpdateDto.java │ │ │ │ │ ├── UserCreateDto.java │ │ │ │ │ ├── UserResponse.java │ │ │ │ │ └── UserUpdateDto.java │ │ │ │ ├── repository │ │ │ │ ├── PostEntity.java │ │ │ │ ├── PostRepository.java │ │ │ │ ├── UserEntity.java │ │ │ │ └── UserRepository.java │ │ │ │ └── service │ │ │ │ ├── PostService.java │ │ │ │ └── UserService.java │ │ └── resources │ │ │ └── application.yaml │ │ └── test │ │ ├── java │ │ └── org │ │ │ └── example │ │ │ └── demo │ │ │ ├── controller │ │ │ ├── HealthCheckTest.java │ │ │ ├── PostControllerTest.java │ │ │ ├── PostCreateControllerTest.java │ │ │ ├── UserControllerTest.java │ │ │ └── UserCreateControllerTest.java │ │ │ ├── repository │ │ │ └── UserRepositoryTest.java │ │ │ └── service │ │ │ ├── PostServiceTest.java │ │ │ └── UserServiceTest.java │ │ └── resources │ │ ├── application-test.yaml │ │ └── sql │ │ ├── delete-all-data.sql │ │ ├── post-controller-test-data.sql │ │ ├── post-create-controller-test-data.sql │ │ ├── post-service-test-data.sql │ │ ├── user-controller-test-data.sql │ │ ├── user-repository-test-data.sql │ │ └── user-service-test-data.sql ├── refactor │ ├── .gitignore │ ├── build.gradle.kts │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle.kts │ └── src │ │ ├── main │ │ ├── java │ │ │ └── org │ │ │ │ └── example │ │ │ │ └── demo │ │ │ │ ├── DemoApplication.java │ │ │ │ ├── common │ │ │ │ ├── controller │ │ │ │ │ ├── ExceptionControllerAdvice.java │ │ │ │ │ └── HealthCheckController.java │ │ │ │ ├── domain │ │ │ │ │ └── exception │ │ │ │ │ │ ├── CertificationCodeNotMatchedException.java │ │ │ │ │ │ └── ResourceNotFoundException.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── SystemClockHolder.java │ │ │ │ │ └── SystemUuidHolder.java │ │ │ │ └── service │ │ │ │ │ └── port │ │ │ │ │ ├── ClockHolder.java │ │ │ │ │ └── UuidHolder.java │ │ │ │ ├── post │ │ │ │ ├── controller │ │ │ │ │ ├── PostController.java │ │ │ │ │ ├── PostCreateController.java │ │ │ │ │ ├── port │ │ │ │ │ │ └── PostService.java │ │ │ │ │ └── response │ │ │ │ │ │ └── PostResponse.java │ │ │ │ ├── domain │ │ │ │ │ ├── Post.java │ │ │ │ │ ├── PostCreate.java │ │ │ │ │ └── PostUpdate.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── PostEntity.java │ │ │ │ │ ├── PostJpaRepository.java │ │ │ │ │ └── PostRepositoryImpl.java │ │ │ │ └── service │ │ │ │ │ ├── PostServiceImpl.java │ │ │ │ │ └── port │ │ │ │ │ └── PostRepository.java │ │ │ │ └── user │ │ │ │ ├── controller │ │ │ │ ├── MyInfoController.java │ │ │ │ ├── UserController.java │ │ │ │ ├── UserCreateController.java │ │ │ │ ├── port │ │ │ │ │ └── UserService.java │ │ │ │ └── response │ │ │ │ │ ├── MyProfileResponse.java │ │ │ │ │ └── UserResponse.java │ │ │ │ ├── domain │ │ │ │ ├── User.java │ │ │ │ ├── UserCreate.java │ │ │ │ ├── UserStatus.java │ │ │ │ └── UserUpdate.java │ │ │ │ ├── infrastructure │ │ │ │ ├── MailSenderImpl.java │ │ │ │ ├── UserEntity.java │ │ │ │ ├── UserJpaRepository.java │ │ │ │ └── UserRepositoryImpl.java │ │ │ │ └── service │ │ │ │ ├── CertificationService.java │ │ │ │ ├── UserServiceImpl.java │ │ │ │ └── port │ │ │ │ ├── MailSender.java │ │ │ │ └── UserRepository.java │ │ └── resources │ │ │ └── application.yaml │ │ └── test │ │ ├── java │ │ └── org │ │ │ └── example │ │ │ └── demo │ │ │ ├── medium │ │ │ ├── HealthCheckTest.java │ │ │ ├── PostControllerTest.java │ │ │ ├── PostCreateControllerTest.java │ │ │ ├── PostServiceTest.java │ │ │ ├── UserControllerTest.java │ │ │ ├── UserCreateControllerTest.java │ │ │ ├── UserJpaRepositoryTest.java │ │ │ └── UserServiceTest.java │ │ │ ├── mock │ │ │ ├── FakeMailSender.java │ │ │ ├── FakePostRepository.java │ │ │ ├── FakeUserRepository.java │ │ │ ├── TestClockHolder.java │ │ │ ├── TestContainer.java │ │ │ └── TestUuidHolder.java │ │ │ ├── post │ │ │ ├── controller │ │ │ │ ├── PostControllerTest.java │ │ │ │ ├── PostCreateControllerTest.java │ │ │ │ └── response │ │ │ │ │ └── PostResponseTest.java │ │ │ ├── domain │ │ │ │ └── PostTest.java │ │ │ └── service │ │ │ │ └── PostServiceTest.java │ │ │ └── user │ │ │ ├── controller │ │ │ ├── MyInfoControllerTest.java │ │ │ ├── UserControllerTest.java │ │ │ ├── UserCreateControllerTest.java │ │ │ └── response │ │ │ │ ├── MyProfileResponseTest.java │ │ │ │ └── UserResponseTest.java │ │ │ ├── domain │ │ │ └── UserTest.java │ │ │ └── service │ │ │ ├── CertificationServiceTest.java │ │ │ └── UserServiceTest.java │ │ └── resources │ │ ├── sql │ │ ├── delete-all-data.sql │ │ ├── post-controller-test-data.sql │ │ ├── post-create-controller-test-data.sql │ │ ├── post-service-test-data.sql │ │ ├── user-controller-test-data.sql │ │ ├── user-repository-test-data.sql │ │ └── user-service-test-data.sql │ │ └── test-application.yaml └── sample │ ├── .gitignore │ ├── build.gradle.kts │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle.kts │ └── src │ ├── main │ └── java │ │ └── org │ │ └── example │ │ └── demo │ │ ├── BadRequestException.java │ │ ├── CalculationRequest.java │ │ ├── CalculationRequestReader.java │ │ ├── Calculator.java │ │ ├── InvalidOperatorException.java │ │ └── SampleApplication.java │ └── test │ └── java │ └── org │ └── example │ └── demo │ ├── CalculationRequestReaderTest.java │ ├── CalculationRequestTest.java │ └── CalculatorTest.java ├── Haneum ├── .gitignore ├── build.gradle ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── main │ └── java │ │ └── depromeet │ │ └── test │ │ └── Haneum │ │ ├── HaneumApplication.java │ │ ├── common │ │ ├── controller │ │ │ ├── ExceptionControllerAdvice.java │ │ │ └── HealthCheckController.java │ │ ├── domain │ │ │ └── exception │ │ │ │ ├── CertificationCodeNotMatchedException.java │ │ │ │ └── ResourceNotFoundException.java │ │ ├── infrastructure │ │ │ ├── SystemClockHolder.java │ │ │ └── SystemUuidHolder.java │ │ └── service │ │ │ └── port │ │ │ ├── ClockHolder.java │ │ │ └── UuidHolder.java │ │ ├── post │ │ ├── controller │ │ │ ├── PostController.java │ │ │ ├── PostCreateController.java │ │ │ ├── port │ │ │ │ └── PostService.java │ │ │ └── response │ │ │ │ └── PostResponse.java │ │ ├── domain │ │ │ ├── Post.java │ │ │ ├── PostCreate.java │ │ │ └── PostUpdate.java │ │ ├── infrastructure │ │ │ ├── PostEntity.java │ │ │ ├── PostJpaRepository.java │ │ │ └── PostRepositoryImpl.java │ │ └── service │ │ │ ├── PostServiceImpl.java │ │ │ └── port │ │ │ └── PostRepository.java │ │ └── user │ │ ├── controller │ │ ├── MyInfoController.java │ │ ├── UserController.java │ │ ├── UserCreateController.java │ │ ├── port │ │ │ └── UserService.java │ │ └── response │ │ │ ├── MyProfileResponse.java │ │ │ └── UserResponse.java │ │ ├── domain │ │ ├── User.java │ │ ├── UserCreate.java │ │ ├── UserStatus.java │ │ └── UserUpdate.java │ │ ├── infrastructure │ │ ├── MailSenderImpl.java │ │ ├── UserEntity.java │ │ ├── UserJpaRepository.java │ │ └── UserRepositoryImpl.java │ │ └── service │ │ ├── CertificationService.java │ │ ├── UserServiceImpl.java │ │ └── port │ │ ├── MailSender.java │ │ └── UserRepository.java │ └── test │ └── java │ └── depromeet │ └── test │ └── Haneum │ ├── HaneumApplicationTests.java │ ├── mock │ ├── FakeMailSender.java │ ├── FakePostRepository.java │ ├── FakeUserRepository.java │ ├── TestClockHolder.java │ ├── TestContainer.java │ └── TestUuidHolder.java │ ├── post │ ├── controller │ │ ├── PostControllerTest.java │ │ ├── PostCreateControllerTest.java │ │ └── response │ │ │ └── PostResponseTest.java │ ├── domain │ │ └── PostTest.java │ └── service │ │ └── PostServiceTest.java │ └── user │ ├── controller │ ├── MyInfoControllerTest.java │ ├── UserControllerTest.java │ ├── UserCreateControllerTest.java │ └── response │ │ ├── MyProfileResponseTest.java │ │ └── UserResponseTest.java │ ├── domain │ └── UserTest.java │ └── service │ ├── CertificationServiceTest.java │ └── UserServiceTest.java ├── Junwon ├── note │ ├── 001_내가_하는_TDD는_왜_실패하는가.md │ ├── 002_테스트에_대한_개요와_개발자가_해야_할_고민.md │ ├── 003_테스트의_필요성과_테스트_3분류.md │ ├── 004_테스트에_필요한_개념.md │ ├── 005_의존성과_Testability.md │ ├── 006_실기_전_사전_지식탐색.md │ ├── 007_테스트_추가하기_-_h2를_이용한_repository_테스트.md │ ├── 008_테스트_추가하기_-_h2를_이용한_service_테스트.md │ ├── 009_테스트_추가하기_-_mockmvc를_이용한_controller_테스트.md │ ├── 010_레이어드_아키텍처의_문제점과_해결책.md │ ├── 011_어떻게_변경할_것인가.md │ ├── 012_패키지_구조_개선.md │ ├── 013_외부_연동을_다루는_방법.md │ ├── 014_도메인과_영속성_객체_구분하기.md │ ├── 015_도메인에_테스트_추가하기.md │ ├── 016_테스트를_소형_테스트로_만들기.md │ ├── 017_컨트롤러를_소형_테스트로_만들기.md │ ├── 018_헥사고날_아키텍처_1.md │ ├── 019_헥사고날_아키텍처_2.md │ ├── 020_헥사고날에_대한_사견.md │ ├── 021_강의_마무리와_부록.md │ └── img │ │ ├── 001_A_Good_Example_Of_Service_Growth.png │ │ ├── 001_The_Way_Traditional_Service_Grow.png │ │ ├── 003_The_Relationship_Between_Test_And_SOLID'.png │ │ ├── 003_Traditional_Test_Classification.png │ │ ├── 004_BBV.png │ │ ├── 004_STV.png │ │ ├── 005_DIP.png │ │ ├── 007_결과_정상_동작.png │ │ ├── 007_동시성_제어_문제_발생.png │ │ ├── 007_테스트_커버리지_측정.png │ │ ├── 008_2-2_까지_모두_성공.png │ │ ├── 008_2-3_이메일_실패.png │ │ ├── 008_JavaMailSender_mocking_후_성공.png │ │ ├── 008_SQL_파일_분리_전_실패.png │ │ ├── 008_SQL_파일_분리_후_성공.png │ │ ├── 008_Service_최종_커버리지_측정.png │ │ ├── 008_커러리지_측정.png │ │ ├── 009_UserCreate에서_메일발송_에러.png │ │ ├── 009_최종_커버리지_측정.png │ │ ├── 010_RepositoryImpl_사용.png │ │ ├── 010_Repository_가_쟁점임.png │ │ ├── 010_개선된_아키텍처.png │ │ ├── 010_도메인_레이어_생성.png │ │ ├── 010_레이어드_아키텍처.png │ │ ├── 010_서비스는_신이야.png │ │ ├── 010_테스트_시_FakeRepository_사용.png │ │ ├── 011_JPA_엔티티와_도메인_모델_분리.png │ │ ├── 011_domain_vo로_로직_이동.png │ │ ├── 011_순환_참조.png │ │ ├── 011_외부_API_등은_의존성_역전_원리_이용.png │ │ ├── 011_패키지_관리_+_의존성_역전.png │ │ ├── 011_패키지_구조_domain_layer_로_구분.png │ │ ├── 011_패키지_구조_domain_layer_로_구분_2.png │ │ ├── 011_패키지_구조_layer_분류.png │ │ ├── 011_패키지_구조_layer_분류_2.png │ │ ├── 012_user_패키지를_만들어_옮기기.png │ │ ├── 012_기존_코드_구조.png │ │ ├── 012_추가_리팩토링_후_구조.png │ │ ├── 012_테스트_패키지_구조_리팩토링.png │ │ ├── 012_테스트_패키지_리팩토링_후_테스트_재확인.png │ │ ├── 012_패키지_구조_리팩토링_후_테스트_재확인.png │ │ ├── 013_FakeMailSender_테스트.png │ │ ├── 013_MailSender_의존성_역전_적용_후_테스트.png │ │ ├── 013_분리된_Repository에_따른_코드_수정_후_테스트.png │ │ ├── 014_완료_후_테스트.png │ │ ├── 015_의존역전_후_테스트.png │ │ ├── 016_Post도_소형_테스트로_변경.png │ │ ├── 016_SpringBoot_어노테이션_제거_후_테스트.png │ │ ├── 016_postServiceTest_리팩토링_후_결과.png │ │ ├── 016_소형_중형_테스트_속도_비교.png │ │ ├── 016_완료_후_전체_테스트.png │ │ ├── 018_input_output_port.png │ │ ├── 018_경계_의존성_역전.png │ │ ├── 018_기존_계층.png │ │ ├── 018_기존_계층_input_output_port.png │ │ ├── 018_올바른_테스트의_가치.png │ │ ├── 018_완성된_헥사고날_아키텍처.png │ │ ├── 018_의존성_역전.png │ │ ├── 018_제거된_계층.png │ │ ├── 019_개발자가_인식하는_애플리케이션.png │ │ ├── 019_헥사고날_재배열.png │ │ ├── 019_헥사고날_해체하기.png │ │ ├── 020_JpaRepository_as_Repository.png │ │ ├── 020_JpaRepository_as_RepositoryImpl's_member.png │ │ ├── 020_JpaRepository_as_RepositoryImpl.png │ │ ├── 020_여전히_단방향.png │ │ ├── 020_트레이드_오프.png │ │ ├── 021_assertAll.png │ │ └── 021_parameterizedTest.png ├── sample │ ├── .gitignore │ ├── .idea │ │ ├── .gitignore │ │ ├── encodings.xml │ │ └── misc.xml │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── sample │ │ │ ├── BadRequestException.java │ │ │ ├── CalculationRequest.java │ │ │ ├── CalculationRequestReader.java │ │ │ ├── Calculator.java │ │ │ ├── InvalidOperatorException.java │ │ │ └── SampleApplication.java │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── sample │ │ ├── CalculationRequestReaderTest.java │ │ ├── CalculationRequestTest.java │ │ └── CalculatorTest.java └── test-code-with-architecture-main │ ├── .idea │ ├── .gitignore │ ├── aws.xml │ ├── checkstyle-idea.xml │ ├── compiler.xml │ ├── encodings.xml │ ├── jarRepositories.xml │ ├── misc.xml │ └── vcs.xml │ ├── .mvn │ └── wrapper │ │ └── maven-wrapper.properties │ ├── README.md │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── demo │ │ │ │ ├── DemoApplication.java │ │ │ │ ├── common │ │ │ │ ├── controller │ │ │ │ │ ├── ExceptionControllerAdvice.java │ │ │ │ │ └── HealthCheckController.java │ │ │ │ ├── domain │ │ │ │ │ └── exception │ │ │ │ │ │ ├── CertificationCodeNotMatchedException.java │ │ │ │ │ │ └── ResourceNotFoundException.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── SystemClockHolder.java │ │ │ │ │ └── SystemUuidHolder.java │ │ │ │ └── service │ │ │ │ │ └── port │ │ │ │ │ ├── ClockHolder.java │ │ │ │ │ └── UuidHolder.java │ │ │ │ ├── post │ │ │ │ ├── controller │ │ │ │ │ ├── PostController.java │ │ │ │ │ ├── PostCreateController.java │ │ │ │ │ ├── port │ │ │ │ │ │ └── PostService.java │ │ │ │ │ └── response │ │ │ │ │ │ └── PostResponse.java │ │ │ │ ├── domain │ │ │ │ │ ├── Post.java │ │ │ │ │ ├── PostCreate.java │ │ │ │ │ └── PostUpdate.java │ │ │ │ ├── infrastructure │ │ │ │ │ ├── PostEntity.java │ │ │ │ │ ├── PostJpaRepository.java │ │ │ │ │ └── PostRepositoryImpl.java │ │ │ │ └── service │ │ │ │ │ ├── PostServiceImpl.java │ │ │ │ │ └── port │ │ │ │ │ └── PostRepository.java │ │ │ │ └── user │ │ │ │ ├── controller │ │ │ │ ├── UserController.java │ │ │ │ ├── UserCreateController.java │ │ │ │ ├── port │ │ │ │ │ └── UserService.java │ │ │ │ └── response │ │ │ │ │ ├── MyProfileResponse.java │ │ │ │ │ └── UserResponse.java │ │ │ │ ├── domain │ │ │ │ ├── User.java │ │ │ │ ├── UserCreate.java │ │ │ │ ├── UserStatus.java │ │ │ │ └── UserUpdate.java │ │ │ │ ├── infrastructure │ │ │ │ ├── MailSenderImpl.java │ │ │ │ ├── UserEntity.java │ │ │ │ ├── UserJpaRepository.java │ │ │ │ └── UserRepositoryImpl.java │ │ │ │ └── service │ │ │ │ ├── CertificationService.java │ │ │ │ ├── UserServiceImpl.java │ │ │ │ └── port │ │ │ │ ├── MailSender.java │ │ │ │ └── UserRepository.java │ │ └── resources │ │ │ └── application.properties │ └── test │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── demo │ │ │ ├── medium │ │ │ ├── HealthCheckControllerTest.java │ │ │ ├── PostControllerTest.java │ │ │ ├── PostCreateControllerTest.java │ │ │ ├── PostServiceTest.java │ │ │ ├── UserControllerTest.java │ │ │ ├── UserCreateControllerTest.java │ │ │ ├── UserJpaRepositoryTest.java │ │ │ └── UserServiceTest.java │ │ │ ├── mock │ │ │ ├── FakeMailSender.java │ │ │ ├── FakePostRepository.java │ │ │ ├── FakeUserRepository.java │ │ │ ├── TestClockHolder.java │ │ │ ├── TestContainer.java │ │ │ └── TestUuidHolder.java │ │ │ ├── post │ │ │ ├── controller │ │ │ │ ├── PostControllerTest.java │ │ │ │ ├── PostCreateControllerTest.java │ │ │ │ └── response │ │ │ │ │ └── PostResponseTest.java │ │ │ ├── domain │ │ │ │ └── PostTest.java │ │ │ └── service │ │ │ │ └── PostServiceTest.java │ │ │ └── user │ │ │ ├── controller │ │ │ ├── UserControllerTest.java │ │ │ ├── UserCreateControllerTest.java │ │ │ └── response │ │ │ │ ├── MyProfileResponseTest.java │ │ │ │ └── UserResponseTest.java │ │ │ ├── domain │ │ │ └── UserTest.java │ │ │ └── service │ │ │ ├── CertificationServiceTest.java │ │ │ └── UserServiceTest.java │ │ └── resources │ │ ├── sql │ │ ├── delete-all-data.sql │ │ ├── post-controller-test-data.sql │ │ ├── post-create-controller-test-data.sql │ │ ├── post-service-test-data.sql │ │ ├── user-controller-test-data.sql │ │ ├── user-repository-test-data.sql │ │ └── user-service-test-data.sql │ │ └── test-application.properties │ └── target │ └── classes │ └── application.properties ├── Nahyeon ├── .gitignore ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── depromeet │ │ │ └── nahyeon │ │ │ ├── NahyeonApplication.java │ │ │ ├── common │ │ │ ├── controller │ │ │ │ ├── ExceptionControllerAdvice.java │ │ │ │ └── HealthCheckController.java │ │ │ ├── domain │ │ │ │ └── exception │ │ │ │ │ ├── CertificationCodeNotMatchedException.java │ │ │ │ │ └── ResourceNotFoundException.java │ │ │ ├── infrastructure │ │ │ │ ├── SystemClockHolder.java │ │ │ │ └── SystemUuidHolder.java │ │ │ └── service │ │ │ │ └── port │ │ │ │ ├── ClockHolder.java │ │ │ │ └── UuidHolder.java │ │ │ ├── post │ │ │ ├── controller │ │ │ │ ├── PostController.java │ │ │ │ ├── PostCreateController.java │ │ │ │ ├── port │ │ │ │ │ └── PostService.java │ │ │ │ └── response │ │ │ │ │ └── PostResponse.java │ │ │ ├── domain │ │ │ │ ├── Post.java │ │ │ │ ├── PostCreate.java │ │ │ │ └── PostUpdate.java │ │ │ ├── infrastructure │ │ │ │ ├── PostEntity.java │ │ │ │ ├── PostJpaRepository.java │ │ │ │ └── PostRepositoryImpl.java │ │ │ └── service │ │ │ │ ├── PostServiceImpl.java │ │ │ │ └── port │ │ │ │ └── PostRepository.java │ │ │ └── user │ │ │ ├── controller │ │ │ ├── MyInfoController.java │ │ │ ├── UserController.java │ │ │ ├── UserCreateController.java │ │ │ ├── port │ │ │ │ └── UserService.java │ │ │ └── response │ │ │ │ ├── MyProfileResponse.java │ │ │ │ └── UserResponse.java │ │ │ ├── domain │ │ │ ├── User.java │ │ │ ├── UserCreate.java │ │ │ ├── UserStatus.java │ │ │ └── UserUpdate.java │ │ │ ├── infrastructure │ │ │ ├── MailSenderImpl.java │ │ │ ├── UserEntity.java │ │ │ ├── UserJpaRepository.java │ │ │ └── UserRepositoryImpl.java │ │ │ └── service │ │ │ ├── CertificationService.java │ │ │ ├── UserServiceImpl.java │ │ │ └── port │ │ │ ├── MailSender.java │ │ │ └── UserRepository.java │ └── resources │ │ └── application.yml │ └── test │ ├── java │ └── com │ │ └── depromeet │ │ └── nahyeon │ │ ├── NahyeonApplicationTests.java │ │ ├── medium │ │ ├── HealthCheckControllerTest.java │ │ ├── PostControllerTest.java │ │ ├── PostCreateControllerTest.java │ │ ├── PostServiceImplTest.java │ │ ├── UserControllerTest.java │ │ ├── UserCreateControllerTest.java │ │ ├── UserJpaRepositoryTest.java │ │ └── UserServiceImplTest.java │ │ ├── mock │ │ ├── FakeMailSender.java │ │ ├── FakePostRepository.java │ │ ├── FakeUserRepository.java │ │ ├── TestClockHolder.java │ │ ├── TestContainer.java │ │ └── TestUuidHolder.java │ │ ├── post │ │ ├── controller │ │ │ ├── PostControllerTest.java │ │ │ ├── PostCreateControllerTest.java │ │ │ └── response │ │ │ │ └── PostResponseTest.java │ │ ├── domain │ │ │ └── PostTest.java │ │ └── service │ │ │ └── PostServiceImplTest.java │ │ └── user │ │ ├── controller │ │ ├── UserControllerTest.java │ │ ├── UserCreateControllerTest.java │ │ └── response │ │ │ ├── MyProfileResponseTest.java │ │ │ └── UserResponseTest.java │ │ ├── domain │ │ └── UserTest.java │ │ └── service │ │ ├── CertificationServiceImplTest.java │ │ └── UserServiceImplTest.java │ └── resources │ ├── sql │ ├── delete-all-data.sql │ ├── post-controller-test-data.sql │ ├── post-create-controller-test-data.sql │ ├── post-service-test-data.sql │ ├── user-controller-test-data.sql │ ├── user-repository-test-data.sql │ └── user-service-test-data.sql │ └── test-application.yml ├── README.md ├── Wonchae ├── sample │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── sample │ │ │ │ ├── BadRequestException.java │ │ │ │ ├── CalculationRequestReader.java │ │ │ │ ├── CalculationRequst.java │ │ │ │ ├── Calculator.java │ │ │ │ ├── InvalidOperatorException.java │ │ │ │ └── SampleApplication.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── sample │ │ ├── CalculationRequestReaderTest.java │ │ ├── CalculationRequestTest.java │ │ ├── CalculatorTest.java │ │ └── SampleApplicationTests.java └── test-code-with-architecture │ ├── .gitignore │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── README.md │ ├── document │ ├── connect-mail-sender.md │ └── resources │ │ ├── 01.mail-settings.png │ │ ├── 02.mail-settings.png │ │ ├── 03.mail-settings.png │ │ ├── 04.mail-settings.png │ │ ├── 05.mail-settings.png │ │ ├── 06.mail-settings.png │ │ └── 07.mail-settings.png │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── demo │ │ │ ├── DemoApplication.java │ │ │ ├── common │ │ │ ├── controller │ │ │ │ ├── ExceptionControllerAdvice.java │ │ │ │ └── HealthCheckController.java │ │ │ ├── domain │ │ │ │ └── exception │ │ │ │ │ ├── CertificationCodeNotMatchedException.java │ │ │ │ │ └── ResourceNotFoundException.java │ │ │ ├── infrastructure │ │ │ │ ├── SystemClockHolder.java │ │ │ │ └── SystemUuidHolder.java │ │ │ └── service │ │ │ │ └── port │ │ │ │ ├── ClockHolder.java │ │ │ │ └── UuidHolder.java │ │ │ ├── post │ │ │ ├── controller │ │ │ │ ├── PostController.java │ │ │ │ ├── PostCreateController.java │ │ │ │ ├── port │ │ │ │ │ └── PostService.java │ │ │ │ └── response │ │ │ │ │ └── PostResponse.java │ │ │ ├── domain │ │ │ │ ├── Post.java │ │ │ │ ├── PostCreate.java │ │ │ │ └── PostUpdate.java │ │ │ ├── infrastructure │ │ │ │ ├── PostEntity.java │ │ │ │ ├── PostJpaRepository.java │ │ │ │ └── PostRepositoryImpl.java │ │ │ └── service │ │ │ │ ├── PostServiceImpl.java │ │ │ │ └── port │ │ │ │ └── PostRepository.java │ │ │ └── user │ │ │ ├── controller │ │ │ ├── UserController.java │ │ │ ├── UserCreateController.java │ │ │ ├── port │ │ │ │ └── UserService.java │ │ │ └── response │ │ │ │ ├── MyProfileResponse.java │ │ │ │ └── UserResponse.java │ │ │ ├── domain │ │ │ ├── User.java │ │ │ ├── UserCreate.java │ │ │ ├── UserStatus.java │ │ │ └── UserUpdate.java │ │ │ ├── infrastructure │ │ │ ├── MailSenderImpl.java │ │ │ ├── UserEntity.java │ │ │ ├── UserJpaRepository.java │ │ │ └── UserRepositoryImpl.java │ │ │ └── service │ │ │ ├── CertificationService.java │ │ │ ├── UserServiceImpl.java │ │ │ └── port │ │ │ ├── MailSender.java │ │ │ └── UserRepository.java │ └── resources │ │ └── application.properties │ └── test │ ├── java │ └── com │ │ └── example │ │ └── demo │ │ ├── medium │ │ ├── HealthCheckTest.java │ │ ├── PostControllerTest.java │ │ ├── PostCreateControllerTest.java │ │ ├── PostServiceImplTest.java │ │ ├── UserControllerTest.java │ │ ├── UserCreateControllerTest.java │ │ ├── UserJpaRepositoryTest.java │ │ └── UserServiceImplTest.java │ │ ├── mock │ │ ├── FakeMailSender.java │ │ ├── FakePostRepository.java │ │ ├── FakeUserRepository.java │ │ ├── TestClockHolder.java │ │ ├── TestContainer.java │ │ └── TestUuidHolder.java │ │ ├── post │ │ ├── controller │ │ │ ├── PostControllerTest.java │ │ │ ├── PostCreateControllerTest.java │ │ │ └── response │ │ │ │ └── PostResponseTest.java │ │ └── domain │ │ │ └── PostTest.java │ │ └── user │ │ ├── controller │ │ ├── UserControllerTest.java │ │ ├── UserCreateControllerTest.java │ │ └── response │ │ │ ├── MyProfileResponseTest.java │ │ │ └── UserResponseTest.java │ │ ├── domain │ │ └── UserTest.java │ │ └── service │ │ └── CertificationServiceImplTest.java │ └── resources │ ├── sql │ ├── delete-all-data.sql │ ├── post-controller-test-data.sql │ ├── post-create-controller-test-data.sql │ ├── post-service-test-data.sql │ ├── user-controller-test-data.sql │ ├── user-repository-test-data.sql │ └── user-service-test-data.sql │ └── test-application.properties ├── Yunbeom ├── .gitignore ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── depromeet │ │ │ └── yunbeom │ │ │ ├── BadRequestException.java │ │ │ ├── CalculationRequest.java │ │ │ ├── CalculationRequestReader.java │ │ │ ├── Calculator.java │ │ │ ├── InvalidOperatorException.java │ │ │ ├── SampleApplication.java │ │ │ ├── YunbeomApplication.java │ │ │ ├── common │ │ │ ├── controller │ │ │ │ ├── ExceptionControllerAdvice.java │ │ │ │ └── HealthCheckController.java │ │ │ ├── infrastructure │ │ │ │ ├── SystemClockHolder.java │ │ │ │ └── SystemUuidHolder.java │ │ │ └── service │ │ │ │ └── port │ │ │ │ ├── ClockHolder.java │ │ │ │ └── UuidHolder.java │ │ │ ├── post │ │ │ ├── controller │ │ │ │ ├── PostController.java │ │ │ │ ├── PostCreateController.java │ │ │ │ ├── port │ │ │ │ │ └── PostService.java │ │ │ │ └── response │ │ │ │ │ └── PostResponse.java │ │ │ ├── domain │ │ │ │ ├── POst.java │ │ │ │ ├── PostCreate.java │ │ │ │ └── PostUpdate.java │ │ │ ├── infrastructure │ │ │ │ ├── PostEntity.java │ │ │ │ ├── PostJpaRepository.java │ │ │ │ └── PostRepositoryImpl.java │ │ │ └── service │ │ │ │ ├── PostServiceImpl.java │ │ │ │ └── port │ │ │ │ └── PostRepository.java │ │ │ └── user │ │ │ ├── controller │ │ │ ├── MyInfoController.java │ │ │ ├── UserController.java │ │ │ ├── UserCreateController.java │ │ │ ├── port │ │ │ │ └── UserService.java │ │ │ ├── request │ │ │ │ └── UserUpdateRequest.java │ │ │ └── response │ │ │ │ ├── MyProfileResponse.java │ │ │ │ └── UserResponse.java │ │ │ ├── domain │ │ │ ├── User.java │ │ │ ├── UserCreate.java │ │ │ ├── UserStatus.java │ │ │ └── UserUpdate.java │ │ │ ├── exception │ │ │ ├── CertificationCodeNotMatchedException.java │ │ │ └── ResourceNotFoundException.java │ │ │ ├── infrastructure │ │ │ ├── MailSenderImpl.java │ │ │ ├── UserEntity.java │ │ │ ├── UserJpaRepository.java │ │ │ └── UserRepositoryImpl.java │ │ │ └── service │ │ │ ├── CertificationService.java │ │ │ ├── UserServiceImpl.java │ │ │ └── port │ │ │ ├── MailSender.java │ │ │ └── UserRepository.java │ └── resources │ │ └── application.yml │ └── test │ ├── java │ └── com │ │ └── depromeet │ │ └── yunbeom │ │ ├── CalculationRequestReaderTest.java │ │ ├── CalculationRequestTest.java │ │ ├── CalculatorTest.java │ │ ├── YunbeomApplicationTests.java │ │ ├── medium │ │ ├── HealthCheckControllerTest.java │ │ ├── post │ │ │ ├── controller │ │ │ │ ├── PostControllerTest.java │ │ │ │ ├── PostCreateControllerTest.java │ │ │ │ └── response │ │ │ │ │ └── PostResponseTest.java │ │ │ └── service │ │ │ │ └── PostServiceTest.java │ │ └── user │ │ │ ├── controller │ │ │ ├── UserControllerTest.java │ │ │ ├── UserCreateControllerTest.java │ │ │ └── response │ │ │ │ ├── MyProfileResponseTest.java │ │ │ │ └── UserResponseTest.java │ │ │ ├── repository │ │ │ └── UserJpaRepositoryTest.java │ │ │ └── service │ │ │ └── UserServiceTest.java │ │ ├── mock │ │ ├── FakeMailSender.java │ │ ├── FakePostRepository.java │ │ ├── FakeUserRepository.java │ │ ├── TestClockHolder.java │ │ ├── TestContainer.java │ │ └── TestUuidHolder.java │ │ ├── post │ │ ├── controller │ │ │ ├── PostControllerTest.java │ │ │ └── PostCreateControllerTest.java │ │ ├── domain │ │ │ └── PostTest.java │ │ └── service │ │ │ └── PostServiceImplTest.java │ │ └── user │ │ ├── controller │ │ ├── UserControllerTest.java │ │ └── UserCreateControllerTest.java │ │ ├── domain │ │ └── UserTest.java │ │ └── service │ │ ├── CertificationServiceTest.java │ │ └── UserServiceTest.java │ └── resources │ ├── application-test.yml │ └── sql │ ├── delete-all-data.sql │ ├── post-controller-test-data.sql │ ├── post-service-test-data.sql │ ├── user-controller-test-data.sql │ ├── user-repository-test-data.sql │ └── user-service-test-data.sql └── domo ├── calculator ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── main │ └── java │ │ ├── BadRequestException.java │ │ ├── CalculationRequest.java │ │ ├── CalculationRequestReader.java │ │ ├── Calculator.java │ │ ├── InvalidOperatorException.java │ │ └── Main.java │ └── test │ └── java │ ├── CalculationRequestReaderTest.java │ ├── CalculationRequestTest.java │ └── CalculatorTest.java └── toy ├── .gitignore ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main ├── java │ └── com │ │ └── domo │ │ ├── ToyApplication.java │ │ ├── common │ │ ├── controller │ │ │ ├── ExceptionControllerAdvice.java │ │ │ └── HealthCheckController.java │ │ ├── domain │ │ │ └── exception │ │ │ │ ├── CertificationCodeNotMatchedException.java │ │ │ │ └── ResourceNotFoundException.java │ │ ├── infrastructure │ │ │ ├── SystemClockHolder.java │ │ │ └── SystemUuidHolder.java │ │ └── service │ │ │ └── port │ │ │ ├── ClockHolder.java │ │ │ └── UuidHolder.java │ │ ├── post │ │ ├── controller │ │ │ ├── PostController.java │ │ │ ├── PostCreateController.java │ │ │ ├── port │ │ │ │ └── PostService.java │ │ │ └── response │ │ │ │ └── PostResponse.java │ │ ├── domain │ │ │ ├── Post.java │ │ │ ├── PostCreate.java │ │ │ └── PostUpdate.java │ │ ├── infstructure │ │ │ ├── PostEntity.java │ │ │ ├── PostJpaRepository.java │ │ │ └── PostRepositoryImpl.java │ │ └── service │ │ │ ├── PostServiceImpl.java │ │ │ └── port │ │ │ └── PostRepository.java │ │ └── user │ │ ├── controller │ │ ├── UserController.java │ │ ├── UserCreateController.java │ │ ├── port │ │ │ └── UserService.java │ │ └── response │ │ │ ├── MyProfileResponse.java │ │ │ └── UserResponse.java │ │ ├── domain │ │ ├── User.java │ │ ├── UserCreate.java │ │ ├── UserStatus.java │ │ └── UserUpdate.java │ │ ├── infstructure │ │ ├── MailSenderImpl.java │ │ ├── UserEntity.java │ │ ├── UserJpaRepository.java │ │ └── UserRepositoryImpl.java │ │ └── service │ │ ├── CertificationService.java │ │ ├── UserServiceImpl.java │ │ └── port │ │ ├── MailSender.java │ │ └── UserRepository.java └── resources │ └── application.yml └── test ├── java └── com │ └── domo │ ├── ToyApplicationTests.java │ ├── medium │ ├── HealthCheckControllerTest.java │ └── UserRepositoryTest.java │ ├── mock │ ├── FakeMailSender.java │ ├── FakePostRepository.java │ ├── FakeUserRepository.java │ ├── TestClockHolder.java │ ├── TestContainer.java │ └── TestUuidHolder.java │ ├── post │ ├── controller │ │ ├── PostControllerTest.java │ │ ├── PostCreateControllerTest.java │ │ └── response │ │ │ └── PostResponseTest.java │ ├── domain │ │ └── PostTest.java │ └── service │ │ └── PostServiceTest.java │ └── user │ ├── controller │ ├── UserControllerTest.java │ ├── UserCreateControllerTest.java │ └── response │ │ ├── MyProfileResponseTest.java │ │ └── UserResponseTest.java │ ├── domain │ └── UserTest.java │ └── service │ ├── CertificationServiceTest.java │ └── UserServiceTest.java └── resources ├── application-test.yml └── sql ├── delete-all-data.sql ├── post-service-test-data.sql ├── user-repository-test-data.sql └── user-service-test-data.sql /.github/ISSUE_TEMPLATE/📚-study.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "📚 study" 3 | about: 공부한 내용은? 4 | title: "📚 " 5 | labels: "📚 study" 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## 📌 오늘의 스터디 이슈는? 11 | - 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## 📌 공부한 내용은?? 2 | - 3 | 4 | ## 📌 느낀 점은? 5 | - -------------------------------------------------------------------------------- /Eunji/h2/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | 7 | ### IntelliJ IDEA ### 8 | .idea/modules.xml 9 | .idea/jarRepositories.xml 10 | .idea/compiler.xml 11 | .idea/libraries/ 12 | *.iws 13 | *.iml 14 | *.ipr 15 | out/ 16 | !**/src/main/**/out/ 17 | !**/src/test/**/out/ 18 | 19 | ### Eclipse ### 20 | .apt_generated 21 | .classpath 22 | .factorypath 23 | .project 24 | .settings 25 | .springBeans 26 | .sts4-cache 27 | bin/ 28 | !**/src/main/**/bin/ 29 | !**/src/test/**/bin/ 30 | 31 | ### NetBeans ### 32 | /nbproject/private/ 33 | /nbbuild/ 34 | /dist/ 35 | /nbdist/ 36 | /.nb-gradle/ 37 | 38 | ### VS Code ### 39 | .vscode/ 40 | 41 | ### Mac OS ### 42 | .DS_Store -------------------------------------------------------------------------------- /Eunji/h2/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Eunji/h2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Eunji/h2/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jun 20 01:46:25 KST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /Eunji/h2/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "h2" 2 | 3 | -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/Main.java: -------------------------------------------------------------------------------- 1 | package org.example.demo; 2 | 3 | import io.swagger.v3.oas.annotations.OpenAPIDefinition; 4 | import io.swagger.v3.oas.annotations.info.Info; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | @SpringBootApplication 9 | @OpenAPIDefinition(info = @Info( 10 | title = "Toy project", 11 | version = "v1", 12 | description = "테스트 코드를 추가하기 위한 연습에 사용될 토이 프로젝트입니다" 13 | )) 14 | public class Main { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(Main.class, args); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/controller/HealthCheckController.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.controller; 2 | 3 | import io.swagger.v3.oas.annotations.tags.Tag; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @Tag(name = "헬스 체크") 9 | @RestController 10 | public class HealthCheckController { 11 | 12 | @GetMapping("/health_check.html") 13 | public ResponseEntity healthCheck() { 14 | return ResponseEntity 15 | .ok() 16 | .build(); 17 | } 18 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/exception/CertificationCodeNotMatchedException.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.exception; 2 | 3 | public class CertificationCodeNotMatchedException extends RuntimeException { 4 | 5 | public CertificationCodeNotMatchedException() { 6 | super("자격 증명에 실패하였습니다."); 7 | } 8 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/exception/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.exception; 2 | 3 | public class ResourceNotFoundException extends RuntimeException { 4 | 5 | public ResourceNotFoundException(String datasource, long id) { 6 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 7 | } 8 | 9 | public ResourceNotFoundException(String datasource, String id) { 10 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 11 | } 12 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/model/UserStatus.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.model; 2 | 3 | public enum UserStatus { 4 | PENDING, INACTIVE, ACTIVE 5 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/model/dto/MyProfileResponse.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.model.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.example.demo.model.UserStatus; 6 | 7 | @Getter 8 | @Setter 9 | public class MyProfileResponse { 10 | 11 | private Long id; 12 | private String email; 13 | private String nickname; 14 | private String address; 15 | private UserStatus status; 16 | private Long lastLoginAt; 17 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/model/dto/PostCreateDto.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.model.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class PostCreateDto { 9 | 10 | private final long writerId; 11 | private final String content; 12 | 13 | @Builder 14 | public PostCreateDto( 15 | @JsonProperty("writerId") long writerId, 16 | @JsonProperty("content") String content) { 17 | this.writerId = writerId; 18 | this.content = content; 19 | } 20 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/model/dto/PostResponse.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.model.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class PostResponse { 9 | 10 | private Long id; 11 | private String content; 12 | private Long createdAt; 13 | private Long modifiedAt; 14 | private UserResponse writer; 15 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/model/dto/PostUpdateDto.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.model.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class PostUpdateDto { 9 | 10 | private final String content; 11 | 12 | @Builder 13 | public PostUpdateDto( 14 | @JsonProperty("content") String content) { 15 | this.content = content; 16 | } 17 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/model/dto/UserCreateDto.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.model.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class UserCreateDto { 9 | 10 | private final String email; 11 | private final String nickname; 12 | private final String address; 13 | 14 | @Builder 15 | public UserCreateDto( 16 | @JsonProperty("email") String email, 17 | @JsonProperty("nickname") String nickname, 18 | @JsonProperty("address") String address) { 19 | this.email = email; 20 | this.nickname = nickname; 21 | this.address = address; 22 | } 23 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/model/dto/UserResponse.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.model.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.example.demo.model.UserStatus; 6 | 7 | @Getter 8 | @Setter 9 | public class UserResponse { 10 | 11 | private Long id; 12 | private String email; 13 | private String nickname; 14 | private UserStatus status; 15 | private Long lastLoginAt; 16 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/model/dto/UserUpdateDto.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.model.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class UserUpdateDto { 9 | 10 | private final String nickname; 11 | private final String address; 12 | 13 | @Builder 14 | public UserUpdateDto( 15 | @JsonProperty("nickname") String nickname, 16 | @JsonProperty("address") String address) { 17 | this.nickname = nickname; 18 | this.address = address; 19 | } 20 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/repository/PostRepository.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface PostRepository extends JpaRepository { 6 | 7 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/java/org/example/demo/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.repository; 2 | 3 | import java.util.Optional; 4 | import org.example.demo.model.UserStatus; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | public interface UserRepository extends JpaRepository { 8 | 9 | Optional findByIdAndStatus(long id, UserStatus userStatus); 10 | 11 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 12 | } -------------------------------------------------------------------------------- /Eunji/h2/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | h2: 3 | console: 4 | enabled: true 5 | path: /h2-console 6 | datasource: 7 | url: jdbc:h2:~/mem-data 8 | driver-class-name: org.h2.Driver 9 | username: sa 10 | password: 11 | jpa: 12 | hibernate: 13 | ddl-auto: create 14 | database-platform: org.hibernate.dialect.H2Dialect 15 | doc: 16 | swagger-ui: 17 | path: /swagger-ui.html 18 | mail: 19 | host: smtp.gmail.com 20 | port: 587 21 | username: ${MAIL_USERNAME} 22 | password: ${MAIL_APPLICATION_PASSWORD} 23 | properties: 24 | mail: 25 | smtp: 26 | auth: true 27 | timeout: 5000 28 | starttls: 29 | enable: true -------------------------------------------------------------------------------- /Eunji/h2/src/test/resources/application-test.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | url: jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1 4 | driver-class-name: org.h2.Driver 5 | username: sa 6 | password: 7 | h2: 8 | console: 9 | enabled: true 10 | jpa: 11 | hibernate: 12 | ddl-auto: create-drop 13 | dialect: org.hibernate.dialect.MariaDBDialect 14 | database-platform: org.hibernate.dialect.H2Dialect 15 | -------------------------------------------------------------------------------- /Eunji/h2/src/test/resources/sql/delete-all-data.sql: -------------------------------------------------------------------------------- 1 | delete from `posts` where 1; 2 | delete from `posts` where 2; 3 | delete from `users` where 1; 4 | delete from `users` where 2; -------------------------------------------------------------------------------- /Eunji/h2/src/test/resources/sql/post-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | 4 | insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) 5 | values (1, 'helloworld', 1678530673958, 0, 1); -------------------------------------------------------------------------------- /Eunji/h2/src/test/resources/sql/post-create-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); -------------------------------------------------------------------------------- /Eunji/h2/src/test/resources/sql/post-service-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); 6 | 7 | insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) 8 | values (100, 'helloworld', 1678530673958, 0, 1); -------------------------------------------------------------------------------- /Eunji/h2/src/test/resources/sql/user-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); -------------------------------------------------------------------------------- /Eunji/h2/src/test/resources/sql/user-repository-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); -------------------------------------------------------------------------------- /Eunji/h2/src/test/resources/sql/user-service-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (10, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (20, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); -------------------------------------------------------------------------------- /Eunji/refactor/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | 7 | ### IntelliJ IDEA ### 8 | .idea/modules.xml 9 | .idea/jarRepositories.xml 10 | .idea/compiler.xml 11 | .idea/libraries/ 12 | *.iws 13 | *.iml 14 | *.ipr 15 | out/ 16 | !**/src/main/**/out/ 17 | !**/src/test/**/out/ 18 | 19 | ### Eclipse ### 20 | .apt_generated 21 | .classpath 22 | .factorypath 23 | .project 24 | .settings 25 | .springBeans 26 | .sts4-cache 27 | bin/ 28 | !**/src/main/**/bin/ 29 | !**/src/test/**/bin/ 30 | 31 | ### NetBeans ### 32 | /nbproject/private/ 33 | /nbbuild/ 34 | /dist/ 35 | /nbdist/ 36 | /.nb-gradle/ 37 | 38 | ### VS Code ### 39 | .vscode/ 40 | 41 | ### Mac OS ### 42 | .DS_Store -------------------------------------------------------------------------------- /Eunji/refactor/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Eunji/refactor/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Eunji/refactor/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jun 27 18:02:36 KST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /Eunji/refactor/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "refactor" 2 | 3 | -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package org.example.demo; 2 | 3 | import io.swagger.v3.oas.annotations.OpenAPIDefinition; 4 | import io.swagger.v3.oas.annotations.info.Info; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | @SpringBootApplication 9 | @OpenAPIDefinition(info = @Info( 10 | title = "Toy project", 11 | version = "v1", 12 | description = "테스트 코드를 추가하기 위한 연습에 사용될 토이 프로젝트입니다" 13 | )) 14 | public class DemoApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(DemoApplication.class, args); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/common/controller/HealthCheckController.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.common.controller; 2 | 3 | import io.swagger.v3.oas.annotations.tags.Tag; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @Tag(name = "헬스 체크") 9 | @RestController 10 | public class HealthCheckController { 11 | 12 | @GetMapping("/health_check.html") 13 | public ResponseEntity healthCheck() { 14 | return ResponseEntity 15 | .ok() 16 | .build(); 17 | } 18 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/common/domain/exception/CertificationCodeNotMatchedException.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.common.domain.exception; 2 | 3 | public class CertificationCodeNotMatchedException extends RuntimeException { 4 | 5 | public CertificationCodeNotMatchedException() { 6 | super("자격 증명에 실패하였습니다."); 7 | } 8 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/common/domain/exception/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.common.domain.exception; 2 | 3 | public class ResourceNotFoundException extends RuntimeException { 4 | 5 | public ResourceNotFoundException(String datasource, long id) { 6 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 7 | } 8 | 9 | public ResourceNotFoundException(String datasource, String id) { 10 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 11 | } 12 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/common/infrastructure/SystemClockHolder.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.common.infrastructure; 2 | 3 | import java.time.Clock; 4 | import org.example.demo.common.service.port.ClockHolder; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class SystemClockHolder implements ClockHolder { 9 | @Override 10 | public long millis() { 11 | return Clock.systemUTC().millis(); 12 | } 13 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/common/infrastructure/SystemUuidHolder.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.common.infrastructure; 2 | 3 | import java.util.UUID; 4 | import org.example.demo.common.service.port.UuidHolder; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class SystemUuidHolder implements UuidHolder { 9 | @Override 10 | public String random() { 11 | return UUID.randomUUID().toString(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/common/service/port/ClockHolder.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.common.service.port; 2 | 3 | public interface ClockHolder { 4 | long millis(); 5 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/common/service/port/UuidHolder.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.common.service.port; 2 | 3 | public interface UuidHolder { 4 | String random(); 5 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/post/controller/port/PostService.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.post.controller.port; 2 | 3 | import org.example.demo.post.domain.Post; 4 | import org.example.demo.post.domain.PostCreate; 5 | import org.example.demo.post.domain.PostUpdate; 6 | 7 | public interface PostService { 8 | 9 | Post getById(long id); 10 | 11 | Post create(PostCreate postCreate); 12 | 13 | Post update(long id, PostUpdate postUpdate); 14 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/post/domain/PostCreate.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class PostCreate { 9 | 10 | private final long writerId; 11 | private final String content; 12 | 13 | @Builder 14 | public PostCreate( 15 | @JsonProperty("writerId") long writerId, 16 | @JsonProperty("content") String content) { 17 | this.writerId = writerId; 18 | this.content = content; 19 | } 20 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/post/domain/PostUpdate.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class PostUpdate { 9 | 10 | private final String content; 11 | 12 | @Builder 13 | public PostUpdate( 14 | @JsonProperty("content") String content) { 15 | this.content = content; 16 | } 17 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/post/infrastructure/PostJpaRepository.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.post.infrastructure; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface PostJpaRepository extends JpaRepository { 6 | 7 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/post/infrastructure/PostRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.post.infrastructure; 2 | 3 | import java.util.Optional; 4 | import lombok.RequiredArgsConstructor; 5 | import org.example.demo.post.domain.Post; 6 | import org.example.demo.post.service.port.PostRepository; 7 | import org.springframework.stereotype.Repository; 8 | 9 | @Repository 10 | @RequiredArgsConstructor 11 | public class PostRepositoryImpl implements PostRepository { 12 | 13 | private final PostJpaRepository postJpaRepository; 14 | 15 | @Override 16 | public Optional findById(long id) { 17 | return postJpaRepository.findById(id).map(PostEntity::toModel); 18 | } 19 | 20 | @Override 21 | public Post save(Post post) { 22 | return postJpaRepository.save(PostEntity.from(post)).toModel(); 23 | } 24 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/post/service/port/PostRepository.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.post.service.port; 2 | 3 | import java.util.Optional; 4 | import org.example.demo.post.domain.Post; 5 | 6 | public interface PostRepository { 7 | Optional findById(long id); 8 | 9 | Post save(Post post); 10 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/user/controller/port/UserService.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.user.controller.port; 2 | 3 | import org.example.demo.user.domain.User; 4 | import org.example.demo.user.domain.UserCreate; 5 | import org.example.demo.user.domain.UserUpdate; 6 | 7 | public interface UserService { 8 | 9 | User getByEmail(String email); 10 | 11 | User getById(long id); 12 | 13 | User create(UserCreate userCreate); 14 | 15 | User update(long id, UserUpdate userUpdate); 16 | 17 | void login(long id); 18 | 19 | void verifyEmail(long id, String certificationCode); 20 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/user/controller/response/UserResponse.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.user.controller.response; 2 | 3 | 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | import org.example.demo.user.domain.User; 7 | import org.example.demo.user.domain.UserStatus; 8 | 9 | @Getter 10 | @Builder 11 | public class UserResponse { 12 | 13 | private Long id; 14 | private String email; 15 | private String nickname; 16 | private UserStatus status; 17 | private Long lastLoginAt; 18 | 19 | public static UserResponse from(User user) { 20 | return UserResponse.builder() 21 | .id(user.getId()) 22 | .email(user.getEmail()) 23 | .nickname(user.getNickname()) 24 | .status(user.getStatus()) 25 | .lastLoginAt(user.getLastLoginAt()) 26 | .build(); 27 | } 28 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/user/domain/UserCreate.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class UserCreate { 9 | 10 | private final String email; 11 | private final String nickname; 12 | private final String address; 13 | 14 | @Builder 15 | public UserCreate( 16 | @JsonProperty("email") String email, 17 | @JsonProperty("nickname") String nickname, 18 | @JsonProperty("address") String address) { 19 | this.email = email; 20 | this.nickname = nickname; 21 | this.address = address; 22 | } 23 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/user/domain/UserStatus.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.user.domain; 2 | 3 | public enum UserStatus { 4 | PENDING, INACTIVE, ACTIVE 5 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/user/domain/UserUpdate.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class UserUpdate { 9 | 10 | private final String nickname; 11 | private final String address; 12 | 13 | @Builder 14 | public UserUpdate( 15 | @JsonProperty("nickname") String nickname, 16 | @JsonProperty("address") String address) { 17 | this.nickname = nickname; 18 | this.address = address; 19 | } 20 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/user/infrastructure/UserJpaRepository.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.user.infrastructure; 2 | 3 | import java.util.Optional; 4 | import org.example.demo.user.domain.UserStatus; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | public interface UserJpaRepository extends JpaRepository { 8 | 9 | Optional findByIdAndStatus(long id, UserStatus userStatus); 10 | 11 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 12 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/user/service/port/MailSender.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.user.service.port; 2 | 3 | public interface MailSender { 4 | void send(String email, String title, String content); 5 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/java/org/example/demo/user/service/port/UserRepository.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.user.service.port; 2 | 3 | import java.util.Optional; 4 | import org.example.demo.user.domain.User; 5 | import org.example.demo.user.domain.UserStatus; 6 | 7 | public interface UserRepository { 8 | 9 | User getById(long id); 10 | 11 | Optional findById(long id); 12 | 13 | Optional findByIdAndStatus(long id, UserStatus userStatus); 14 | 15 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 16 | 17 | User save(User user); 18 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | h2: 3 | console: 4 | enabled: true 5 | path: /h2-console 6 | datasource: 7 | url: jdbc:h2:~/mem-data; 8 | driverClassName: org.h2.Driver 9 | username: sa 10 | password: 11 | hikari: 12 | maximum-pool-size: 5 13 | jpa: 14 | hibernate: 15 | ddl-auto: create 16 | database-platform: org.hibernate.dialect.H2Dialect 17 | doc: 18 | swagger-ui: 19 | path: /swagger-ui.html 20 | 21 | mail: 22 | host: smtp.gmail.com 23 | port: 587 24 | username: ${MAIL_USERNAME} 25 | password: ${MAIL_APPLICATION_PASSWORD} 26 | properties: 27 | mail: 28 | smtp: 29 | auth: true 30 | timeout: 5000 31 | starttls: 32 | enable: true 33 | -------------------------------------------------------------------------------- /Eunji/refactor/src/test/java/org/example/demo/mock/FakeMailSender.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.mock; 2 | 3 | import org.example.demo.user.service.port.MailSender; 4 | 5 | public class FakeMailSender implements MailSender { 6 | 7 | public String email; 8 | public String title; 9 | public String content; 10 | 11 | @Override 12 | public void send(String email, String title, String content) { 13 | this.email = email; 14 | this.title = title; 15 | this.content = content; 16 | } 17 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/test/java/org/example/demo/mock/TestClockHolder.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.mock; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.example.demo.common.service.port.ClockHolder; 5 | 6 | @RequiredArgsConstructor 7 | public class TestClockHolder implements ClockHolder { 8 | 9 | private final long millis; 10 | 11 | @Override 12 | public long millis() { 13 | return millis; 14 | } 15 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/test/java/org/example/demo/mock/TestUuidHolder.java: -------------------------------------------------------------------------------- 1 | package org.example.demo.mock; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.example.demo.common.service.port.UuidHolder; 5 | 6 | @RequiredArgsConstructor 7 | public class TestUuidHolder implements UuidHolder { 8 | 9 | private final String uuid; 10 | 11 | @Override 12 | public String random() { 13 | return uuid; 14 | } 15 | } -------------------------------------------------------------------------------- /Eunji/refactor/src/test/resources/sql/delete-all-data.sql: -------------------------------------------------------------------------------- 1 | delete from `posts` where 1; 2 | delete from `posts` where 2; 3 | delete from `users` where 1; 4 | delete from `users` where 2; -------------------------------------------------------------------------------- /Eunji/refactor/src/test/resources/sql/post-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | 4 | insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) 5 | values (1, 'helloworld', 1678530673958, 0, 1); -------------------------------------------------------------------------------- /Eunji/refactor/src/test/resources/sql/post-create-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); -------------------------------------------------------------------------------- /Eunji/refactor/src/test/resources/sql/post-service-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); 6 | 7 | insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) 8 | values (100, 'helloworld', 1678530673958, 0, 1); -------------------------------------------------------------------------------- /Eunji/refactor/src/test/resources/sql/user-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); -------------------------------------------------------------------------------- /Eunji/refactor/src/test/resources/sql/user-repository-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); -------------------------------------------------------------------------------- /Eunji/refactor/src/test/resources/sql/user-service-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (10, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (20, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); -------------------------------------------------------------------------------- /Eunji/refactor/src/test/resources/test-application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | url: jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1 4 | driver-class-name: org.h2.Driver 5 | username: sa 6 | password: 7 | h2: 8 | console: 9 | enabled: true 10 | jpa: 11 | hibernate: 12 | ddl-auto: create-drop 13 | dialect: org.hibernate.dialect.MariaDBDialect 14 | database-platform: org.hibernate.dialect.H2Dialect 15 | -------------------------------------------------------------------------------- /Eunji/sample/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | 7 | ### IntelliJ IDEA ### 8 | .idea/modules.xml 9 | .idea/jarRepositories.xml 10 | .idea/compiler.xml 11 | .idea/libraries/ 12 | *.iws 13 | *.iml 14 | *.ipr 15 | out/ 16 | !**/src/main/**/out/ 17 | !**/src/test/**/out/ 18 | 19 | ### Eclipse ### 20 | .apt_generated 21 | .classpath 22 | .factorypath 23 | .project 24 | .settings 25 | .springBeans 26 | .sts4-cache 27 | bin/ 28 | !**/src/main/**/bin/ 29 | !**/src/test/**/bin/ 30 | 31 | ### NetBeans ### 32 | /nbproject/private/ 33 | /nbbuild/ 34 | /dist/ 35 | /nbdist/ 36 | /.nb-gradle/ 37 | 38 | ### VS Code ### 39 | .vscode/ 40 | 41 | ### Mac OS ### 42 | .DS_Store -------------------------------------------------------------------------------- /Eunji/sample/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("java") 3 | } 4 | 5 | group = "org.example.demo" 6 | version = "1.0-SNAPSHOT" 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | testImplementation(platform("org.junit:junit-bom:5.9.1")) 14 | testImplementation("org.junit.jupiter:junit-jupiter") 15 | } 16 | 17 | tasks.test { 18 | useJUnitPlatform() 19 | } -------------------------------------------------------------------------------- /Eunji/sample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Eunji/sample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Eunji/sample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jun 10 00:16:04 KST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /Eunji/sample/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "sample" -------------------------------------------------------------------------------- /Eunji/sample/src/main/java/org/example/demo/BadRequestException.java: -------------------------------------------------------------------------------- 1 | package org.example.demo; 2 | 3 | public class BadRequestException extends RuntimeException { 4 | 5 | public BadRequestException() { 6 | super("Invalid input size, you must input 3 length"); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Eunji/sample/src/main/java/org/example/demo/CalculationRequestReader.java: -------------------------------------------------------------------------------- 1 | package org.example.demo; 2 | 3 | import java.util.Scanner; 4 | 5 | public class CalculationRequestReader { 6 | 7 | public CalculationRequest read() { 8 | Scanner scanner = new Scanner(System.in); 9 | System.out.println("Enter two numbers and an operator (e.g 1 + 1): "); 10 | String result = scanner.nextLine(); 11 | return new CalculationRequest( 12 | result.split(" ") 13 | ); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Eunji/sample/src/main/java/org/example/demo/Calculator.java: -------------------------------------------------------------------------------- 1 | package org.example.demo; 2 | 3 | public class Calculator { 4 | 5 | public long calculate(long num1, String operator, long num2) { 6 | return switch (operator) { 7 | case "+" -> num1 + num2; 8 | case "-" -> num1 - num2; 9 | case "*" -> num1 * num2; 10 | case "/" -> num1 / num2; 11 | default -> throw new InvalidOperatorException(); 12 | }; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Eunji/sample/src/main/java/org/example/demo/InvalidOperatorException.java: -------------------------------------------------------------------------------- 1 | package org.example.demo; 2 | 3 | public class InvalidOperatorException extends RuntimeException { 4 | public InvalidOperatorException() { 5 | super("Invalid operator, you need to choose one of +, -, *, /"); 6 | } 7 | 8 | } 9 | -------------------------------------------------------------------------------- /Eunji/sample/src/main/java/org/example/demo/SampleApplication.java: -------------------------------------------------------------------------------- 1 | package org.example.demo; 2 | 3 | public class SampleApplication { 4 | 5 | public static void main(String[] args) { 6 | CalculationRequest calculationRequest = new CalculationRequestReader().read(); 7 | long answer = new Calculator().calculate( 8 | calculationRequest.getNum1(), 9 | calculationRequest.getOperator(), 10 | calculationRequest.getNum2() 11 | ); 12 | System.out.println(answer); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Eunji/sample/src/test/java/org/example/demo/CalculationRequestReaderTest.java: -------------------------------------------------------------------------------- 1 | package org.example.demo; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import java.io.ByteArrayInputStream; 6 | import org.junit.jupiter.api.Test; 7 | 8 | public class CalculationRequestReaderTest { 9 | 10 | @Test 11 | public void System_in_으로_데이터를_읽어들일_수_있다() { 12 | // given 13 | CalculationRequestReader calculationRequestReader = new CalculationRequestReader(); 14 | 15 | // when 16 | System.setIn(new ByteArrayInputStream("2 + 3".getBytes())); 17 | CalculationRequest result = calculationRequestReader.read(); 18 | 19 | // then 20 | assertEquals(2, result.getNum1()); 21 | assertEquals("+", result.getOperator()); 22 | assertEquals(3, result.getNum2()); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Haneum/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | 39 | # YAML files 40 | *.yml 41 | 42 | #properties files 43 | *.properties -------------------------------------------------------------------------------- /Haneum/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Haneum' 2 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/HaneumApplication.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class HaneumApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(HaneumApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/common/controller/HealthCheckController.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.common.controller; 2 | 3 | import io.swagger.v3.oas.annotations.tags.Tag; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @Tag(name = "헬스 체크") 9 | @RestController 10 | public class HealthCheckController { 11 | 12 | @GetMapping("/health_check.html") 13 | public ResponseEntity healthCheck() { 14 | return ResponseEntity 15 | .ok() 16 | .build(); 17 | } 18 | } -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/common/domain/exception/CertificationCodeNotMatchedException.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.common.domain.exception; 2 | 3 | public class CertificationCodeNotMatchedException extends RuntimeException { 4 | 5 | public CertificationCodeNotMatchedException() { 6 | super("자격 증명에 실패하였습니다."); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/common/domain/exception/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.common.domain.exception; 2 | 3 | public class ResourceNotFoundException extends RuntimeException { 4 | 5 | public ResourceNotFoundException(String datasource, long id) { 6 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 7 | } 8 | 9 | public ResourceNotFoundException(String datasource, String id) { 10 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/common/infrastructure/SystemClockHolder.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.common.infrastructure; 2 | 3 | import java.time.Clock; 4 | import org.springframework.stereotype.Component; 5 | 6 | import depromeet.test.Haneum.common.service.port.ClockHolder; 7 | 8 | @Component 9 | public class SystemClockHolder implements ClockHolder { 10 | 11 | @Override 12 | public long millis() { 13 | return Clock.systemUTC().millis(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/common/infrastructure/SystemUuidHolder.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.common.infrastructure; 2 | 3 | import java.util.UUID; 4 | import org.springframework.stereotype.Component; 5 | 6 | import depromeet.test.Haneum.common.service.port.UuidHolder; 7 | 8 | @Component 9 | public class SystemUuidHolder implements UuidHolder { 10 | 11 | @Override 12 | public String random() { 13 | return UUID.randomUUID().toString(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/common/service/port/ClockHolder.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.common.service.port; 2 | 3 | public interface ClockHolder { 4 | 5 | long millis(); 6 | } 7 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/common/service/port/UuidHolder.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.common.service.port; 2 | 3 | public interface UuidHolder { 4 | 5 | String random(); 6 | } 7 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/post/controller/port/PostService.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.post.controller.port; 2 | 3 | import depromeet.test.Haneum.post.domain.Post; 4 | import depromeet.test.Haneum.post.domain.PostCreate; 5 | import depromeet.test.Haneum.post.domain.PostUpdate; 6 | 7 | public interface PostService { 8 | 9 | Post getById(long id); 10 | 11 | Post create(PostCreate postCreate); 12 | 13 | Post update(long id, PostUpdate postUpdate); 14 | } 15 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/post/domain/PostCreate.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class PostCreate { 9 | 10 | private final long writerId; 11 | private final String content; 12 | 13 | @Builder 14 | public PostCreate( 15 | @JsonProperty("writerId") long writerId, 16 | @JsonProperty("content") String content) { 17 | this.writerId = writerId; 18 | this.content = content; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/post/domain/PostUpdate.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class PostUpdate { 9 | 10 | private final String content; 11 | 12 | @Builder 13 | public PostUpdate( 14 | @JsonProperty("content") String content) { 15 | this.content = content; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/post/infrastructure/PostJpaRepository.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.post.infrastructure; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface PostJpaRepository extends JpaRepository { 6 | 7 | } -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/post/service/port/PostRepository.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.post.service.port; 2 | 3 | import java.util.Optional; 4 | 5 | import depromeet.test.Haneum.post.domain.Post; 6 | 7 | public interface PostRepository { 8 | 9 | Optional findById(long id); 10 | 11 | Post save(Post post); 12 | } 13 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/user/controller/port/UserService.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.user.controller.port; 2 | 3 | import depromeet.test.Haneum.user.domain.User; 4 | import depromeet.test.Haneum.user.domain.UserCreate; 5 | import depromeet.test.Haneum.user.domain.UserUpdate; 6 | 7 | public interface UserService { 8 | 9 | User getByEmail(String email); 10 | 11 | User getById(long id); 12 | 13 | User create(UserCreate userCreate); 14 | 15 | User update(long id, UserUpdate userUpdate); 16 | 17 | void login(long id); 18 | 19 | void verifyEmail(long id, String certificationCode); 20 | } 21 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/user/domain/UserCreate.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class UserCreate { 9 | 10 | private final String email; 11 | private final String nickname; 12 | private final String address; 13 | 14 | @Builder 15 | public UserCreate( 16 | @JsonProperty("email") String email, 17 | @JsonProperty("nickname") String nickname, 18 | @JsonProperty("address") String address) { 19 | this.email = email; 20 | this.nickname = nickname; 21 | this.address = address; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/user/domain/UserStatus.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.user.domain; 2 | 3 | public enum UserStatus { 4 | PENDING, INACTIVE, ACTIVE 5 | } 6 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/user/domain/UserUpdate.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class UserUpdate { 9 | 10 | private final String nickname; 11 | private final String address; 12 | 13 | @Builder 14 | public UserUpdate( 15 | @JsonProperty("nickname") String nickname, 16 | @JsonProperty("address") String address) { 17 | this.nickname = nickname; 18 | this.address = address; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/user/infrastructure/UserJpaRepository.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.user.infrastructure; 2 | 3 | import java.util.Optional; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import depromeet.test.Haneum.user.domain.UserStatus; 8 | 9 | public interface UserJpaRepository extends JpaRepository { 10 | 11 | Optional findByIdAndStatus(long id, UserStatus userStatus); 12 | 13 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 14 | } 15 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/user/service/port/MailSender.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.user.service.port; 2 | 3 | public interface MailSender { 4 | 5 | void send(String email, String title, String content); 6 | } 7 | -------------------------------------------------------------------------------- /Haneum/src/main/java/depromeet/test/Haneum/user/service/port/UserRepository.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.user.service.port; 2 | 3 | import java.util.Optional; 4 | 5 | import depromeet.test.Haneum.user.domain.User; 6 | import depromeet.test.Haneum.user.domain.UserStatus; 7 | 8 | public interface UserRepository { 9 | 10 | User getById(long id); 11 | 12 | Optional findById(long id); 13 | 14 | Optional findByIdAndStatus(long id, UserStatus userStatus); 15 | 16 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 17 | 18 | User save(User user); 19 | } 20 | -------------------------------------------------------------------------------- /Haneum/src/test/java/depromeet/test/Haneum/HaneumApplicationTests.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class HaneumApplicationTests { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Haneum/src/test/java/depromeet/test/Haneum/mock/FakeMailSender.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.mock; 2 | 3 | import depromeet.test.Haneum.user.service.port.MailSender; 4 | 5 | public class FakeMailSender implements MailSender { 6 | 7 | public String email; 8 | public String title; 9 | public String content; 10 | 11 | @Override 12 | public void send(String email, String title, String content) { 13 | this.email = email; 14 | this.title = title; 15 | this.content = content; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Haneum/src/test/java/depromeet/test/Haneum/mock/TestClockHolder.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.mock; 2 | 3 | import depromeet.test.Haneum.common.service.port.ClockHolder; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @RequiredArgsConstructor 7 | public class TestClockHolder implements ClockHolder { 8 | 9 | private final long millis; 10 | 11 | @Override 12 | public long millis() { 13 | return millis; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Haneum/src/test/java/depromeet/test/Haneum/mock/TestUuidHolder.java: -------------------------------------------------------------------------------- 1 | package depromeet.test.Haneum.mock; 2 | 3 | import depromeet.test.Haneum.common.service.port.UuidHolder; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @RequiredArgsConstructor 7 | public class TestUuidHolder implements UuidHolder { 8 | 9 | private final String uuid; 10 | 11 | @Override 12 | public String random() { 13 | return uuid; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Junwon/note/012_패키지_구조_개선.md: -------------------------------------------------------------------------------- 1 | 패키지 리팩토링! 2 | 1. 기존 프로젝트 코드들을 user 패키지를 생성하여 옮기기 3 | - 기존 구조 4 | 5 | ![012_기존_코드_구조.png](img/012_기존_코드_구조.png) 6 | - 변경된 구조 7 | 8 | ![012_user_패키지를_만들어_옮기기.png](img/012_user_패키지를_만들어_옮기기.png) 9 | 10 | 2. 추가 리팩토링 진행 11 | - model -> domain 12 | - dto 네이밍 -> 제거(이미 역할을 내포하고 있음.) 13 | - repository -> infrastructure 14 | 15 | ![012_추가_리팩토링_후_구조.png](img/012_추가_리팩토링_후_구조.png) 16 | 17 | 3. 리팩토링 후 테스트 재확인 18 | ![012_패키지_구조_리팩토링_후_테스트_재확인.png](img/012_패키지_구조_리팩토링_후_테스트_재확인.png) 19 | 20 | - 정상 동작하는 것을 확인! 21 | 22 | 4. 테스트의 구조 또한 위와 동일하게 변경 23 | ![012_테스트_패키지_구조_리팩토링.png](img/012_테스트_패키지_구조_리팩토링.png) 24 | 25 | 5. 리팩토링 후 테스트 재확인! 26 | ![012_테스트_패키지_리팩토링_후_테스트_재확인.png](img/012_테스트_패키지_리팩토링_후_테스트_재확인.png) 27 | 28 | 6. 끝! 29 | - 헥사고날과 같은 더 고도화된 아키텍처도 존재함. 30 | - 헥사고날은 도입에 너무 큰 리소스가 듦... 31 | - 강의 마지막 즈음엔 헥사고날과 같은 고도화된 아키텍처에 대해서도 학습 예정! -------------------------------------------------------------------------------- /Junwon/note/img/001_A_Good_Example_Of_Service_Growth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/001_A_Good_Example_Of_Service_Growth.png -------------------------------------------------------------------------------- /Junwon/note/img/001_The_Way_Traditional_Service_Grow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/001_The_Way_Traditional_Service_Grow.png -------------------------------------------------------------------------------- /Junwon/note/img/003_The_Relationship_Between_Test_And_SOLID'.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/003_The_Relationship_Between_Test_And_SOLID'.png -------------------------------------------------------------------------------- /Junwon/note/img/003_Traditional_Test_Classification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/003_Traditional_Test_Classification.png -------------------------------------------------------------------------------- /Junwon/note/img/004_BBV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/004_BBV.png -------------------------------------------------------------------------------- /Junwon/note/img/004_STV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/004_STV.png -------------------------------------------------------------------------------- /Junwon/note/img/005_DIP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/005_DIP.png -------------------------------------------------------------------------------- /Junwon/note/img/007_결과_정상_동작.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/007_결과_정상_동작.png -------------------------------------------------------------------------------- /Junwon/note/img/007_동시성_제어_문제_발생.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/007_동시성_제어_문제_발생.png -------------------------------------------------------------------------------- /Junwon/note/img/007_테스트_커버리지_측정.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/007_테스트_커버리지_측정.png -------------------------------------------------------------------------------- /Junwon/note/img/008_2-2_까지_모두_성공.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/008_2-2_까지_모두_성공.png -------------------------------------------------------------------------------- /Junwon/note/img/008_2-3_이메일_실패.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/008_2-3_이메일_실패.png -------------------------------------------------------------------------------- /Junwon/note/img/008_JavaMailSender_mocking_후_성공.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/008_JavaMailSender_mocking_후_성공.png -------------------------------------------------------------------------------- /Junwon/note/img/008_SQL_파일_분리_전_실패.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/008_SQL_파일_분리_전_실패.png -------------------------------------------------------------------------------- /Junwon/note/img/008_SQL_파일_분리_후_성공.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/008_SQL_파일_분리_후_성공.png -------------------------------------------------------------------------------- /Junwon/note/img/008_Service_최종_커버리지_측정.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/008_Service_최종_커버리지_측정.png -------------------------------------------------------------------------------- /Junwon/note/img/008_커러리지_측정.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/008_커러리지_측정.png -------------------------------------------------------------------------------- /Junwon/note/img/009_UserCreate에서_메일발송_에러.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/009_UserCreate에서_메일발송_에러.png -------------------------------------------------------------------------------- /Junwon/note/img/009_최종_커버리지_측정.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/009_최종_커버리지_측정.png -------------------------------------------------------------------------------- /Junwon/note/img/010_RepositoryImpl_사용.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/010_RepositoryImpl_사용.png -------------------------------------------------------------------------------- /Junwon/note/img/010_Repository_가_쟁점임.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/010_Repository_가_쟁점임.png -------------------------------------------------------------------------------- /Junwon/note/img/010_개선된_아키텍처.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/010_개선된_아키텍처.png -------------------------------------------------------------------------------- /Junwon/note/img/010_도메인_레이어_생성.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/010_도메인_레이어_생성.png -------------------------------------------------------------------------------- /Junwon/note/img/010_레이어드_아키텍처.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/010_레이어드_아키텍처.png -------------------------------------------------------------------------------- /Junwon/note/img/010_서비스는_신이야.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/010_서비스는_신이야.png -------------------------------------------------------------------------------- /Junwon/note/img/010_테스트_시_FakeRepository_사용.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/010_테스트_시_FakeRepository_사용.png -------------------------------------------------------------------------------- /Junwon/note/img/011_JPA_엔티티와_도메인_모델_분리.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/011_JPA_엔티티와_도메인_모델_분리.png -------------------------------------------------------------------------------- /Junwon/note/img/011_domain_vo로_로직_이동.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/011_domain_vo로_로직_이동.png -------------------------------------------------------------------------------- /Junwon/note/img/011_순환_참조.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/011_순환_참조.png -------------------------------------------------------------------------------- /Junwon/note/img/011_외부_API_등은_의존성_역전_원리_이용.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/011_외부_API_등은_의존성_역전_원리_이용.png -------------------------------------------------------------------------------- /Junwon/note/img/011_패키지_관리_+_의존성_역전.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/011_패키지_관리_+_의존성_역전.png -------------------------------------------------------------------------------- /Junwon/note/img/011_패키지_구조_domain_layer_로_구분.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/011_패키지_구조_domain_layer_로_구분.png -------------------------------------------------------------------------------- /Junwon/note/img/011_패키지_구조_domain_layer_로_구분_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/011_패키지_구조_domain_layer_로_구분_2.png -------------------------------------------------------------------------------- /Junwon/note/img/011_패키지_구조_layer_분류.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/011_패키지_구조_layer_분류.png -------------------------------------------------------------------------------- /Junwon/note/img/011_패키지_구조_layer_분류_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/011_패키지_구조_layer_분류_2.png -------------------------------------------------------------------------------- /Junwon/note/img/012_user_패키지를_만들어_옮기기.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/012_user_패키지를_만들어_옮기기.png -------------------------------------------------------------------------------- /Junwon/note/img/012_기존_코드_구조.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/012_기존_코드_구조.png -------------------------------------------------------------------------------- /Junwon/note/img/012_추가_리팩토링_후_구조.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/012_추가_리팩토링_후_구조.png -------------------------------------------------------------------------------- /Junwon/note/img/012_테스트_패키지_구조_리팩토링.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/012_테스트_패키지_구조_리팩토링.png -------------------------------------------------------------------------------- /Junwon/note/img/012_테스트_패키지_리팩토링_후_테스트_재확인.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/012_테스트_패키지_리팩토링_후_테스트_재확인.png -------------------------------------------------------------------------------- /Junwon/note/img/012_패키지_구조_리팩토링_후_테스트_재확인.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/012_패키지_구조_리팩토링_후_테스트_재확인.png -------------------------------------------------------------------------------- /Junwon/note/img/013_FakeMailSender_테스트.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/013_FakeMailSender_테스트.png -------------------------------------------------------------------------------- /Junwon/note/img/013_MailSender_의존성_역전_적용_후_테스트.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/013_MailSender_의존성_역전_적용_후_테스트.png -------------------------------------------------------------------------------- /Junwon/note/img/013_분리된_Repository에_따른_코드_수정_후_테스트.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/013_분리된_Repository에_따른_코드_수정_후_테스트.png -------------------------------------------------------------------------------- /Junwon/note/img/014_완료_후_테스트.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/014_완료_후_테스트.png -------------------------------------------------------------------------------- /Junwon/note/img/015_의존역전_후_테스트.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/015_의존역전_후_테스트.png -------------------------------------------------------------------------------- /Junwon/note/img/016_Post도_소형_테스트로_변경.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/016_Post도_소형_테스트로_변경.png -------------------------------------------------------------------------------- /Junwon/note/img/016_SpringBoot_어노테이션_제거_후_테스트.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/016_SpringBoot_어노테이션_제거_후_테스트.png -------------------------------------------------------------------------------- /Junwon/note/img/016_postServiceTest_리팩토링_후_결과.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/016_postServiceTest_리팩토링_후_결과.png -------------------------------------------------------------------------------- /Junwon/note/img/016_소형_중형_테스트_속도_비교.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/016_소형_중형_테스트_속도_비교.png -------------------------------------------------------------------------------- /Junwon/note/img/016_완료_후_전체_테스트.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/016_완료_후_전체_테스트.png -------------------------------------------------------------------------------- /Junwon/note/img/018_input_output_port.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/018_input_output_port.png -------------------------------------------------------------------------------- /Junwon/note/img/018_경계_의존성_역전.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/018_경계_의존성_역전.png -------------------------------------------------------------------------------- /Junwon/note/img/018_기존_계층.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/018_기존_계층.png -------------------------------------------------------------------------------- /Junwon/note/img/018_기존_계층_input_output_port.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/018_기존_계층_input_output_port.png -------------------------------------------------------------------------------- /Junwon/note/img/018_올바른_테스트의_가치.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/018_올바른_테스트의_가치.png -------------------------------------------------------------------------------- /Junwon/note/img/018_완성된_헥사고날_아키텍처.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/018_완성된_헥사고날_아키텍처.png -------------------------------------------------------------------------------- /Junwon/note/img/018_의존성_역전.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/018_의존성_역전.png -------------------------------------------------------------------------------- /Junwon/note/img/018_제거된_계층.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/018_제거된_계층.png -------------------------------------------------------------------------------- /Junwon/note/img/019_개발자가_인식하는_애플리케이션.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/019_개발자가_인식하는_애플리케이션.png -------------------------------------------------------------------------------- /Junwon/note/img/019_헥사고날_재배열.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/019_헥사고날_재배열.png -------------------------------------------------------------------------------- /Junwon/note/img/019_헥사고날_해체하기.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/019_헥사고날_해체하기.png -------------------------------------------------------------------------------- /Junwon/note/img/020_JpaRepository_as_Repository.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/020_JpaRepository_as_Repository.png -------------------------------------------------------------------------------- /Junwon/note/img/020_JpaRepository_as_RepositoryImpl's_member.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/020_JpaRepository_as_RepositoryImpl's_member.png -------------------------------------------------------------------------------- /Junwon/note/img/020_JpaRepository_as_RepositoryImpl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/020_JpaRepository_as_RepositoryImpl.png -------------------------------------------------------------------------------- /Junwon/note/img/020_여전히_단방향.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/020_여전히_단방향.png -------------------------------------------------------------------------------- /Junwon/note/img/020_트레이드_오프.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/020_트레이드_오프.png -------------------------------------------------------------------------------- /Junwon/note/img/021_assertAll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/021_assertAll.png -------------------------------------------------------------------------------- /Junwon/note/img/021_parameterizedTest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Junwon/note/img/021_parameterizedTest.png -------------------------------------------------------------------------------- /Junwon/sample/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | !**/src/main/**/target/ 4 | !**/src/test/**/target/ 5 | 6 | ### IntelliJ IDEA ### 7 | .idea/modules.xml 8 | .idea/jarRepositories.xml 9 | .idea/compiler.xml 10 | .idea/libraries/ 11 | *.iws 12 | *.iml 13 | *.ipr 14 | 15 | ### Eclipse ### 16 | .apt_generated 17 | .classpath 18 | .factorypath 19 | .project 20 | .settings 21 | .springBeans 22 | .sts4-cache 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | !**/src/main/**/build/ 32 | !**/src/test/**/build/ 33 | 34 | ### VS Code ### 35 | .vscode/ 36 | 37 | ### Mac OS ### 38 | .DS_Store -------------------------------------------------------------------------------- /Junwon/sample/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /Junwon/sample/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Junwon/sample/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Junwon/sample/src/main/java/com/example/sample/BadRequestException.java: -------------------------------------------------------------------------------- 1 | package swag.qrorder.sample.src.main.java.com.example.sample; 2 | 3 | public class BadRequestException extends RuntimeException { 4 | public BadRequestException() { 5 | super("Bad Request, ilvalid size"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Junwon/sample/src/main/java/com/example/sample/CalculationRequestReader.java: -------------------------------------------------------------------------------- 1 | package swag.qrorder.sample.src.main.java.com.example.sample; 2 | 3 | import java.util.Scanner; 4 | 5 | public class CalculationRequestReader { 6 | public CalculationRequest read(){ 7 | 8 | Scanner scanner = new Scanner(System.in); 9 | System.out.println("Enter two number: "); 10 | String result = scanner.nextLine(); 11 | String[] parts = result.split(" "); 12 | return new CalculationRequest(parts); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Junwon/sample/src/main/java/com/example/sample/Calculator.java: -------------------------------------------------------------------------------- 1 | package swag.qrorder.sample.src.main.java.com.example.sample; 2 | 3 | public class Calculator { 4 | public long calculate(long num1, String operation, long num2) { 5 | return switch (operation) { 6 | case "+" -> num1 + num2; 7 | case "-" -> num1 - num2; 8 | case "*" -> num1 * num2; 9 | case "/" -> num1 / num2; 10 | default -> throw new InvalidOperatorException(); 11 | }; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Junwon/sample/src/main/java/com/example/sample/InvalidOperatorException.java: -------------------------------------------------------------------------------- 1 | package swag.qrorder.sample.src.main.java.com.example.sample; 2 | 3 | public class InvalidOperatorException extends RuntimeException { 4 | public InvalidOperatorException() { 5 | super("Invalid operator, (+, -, *, /)"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Junwon/sample/src/main/java/com/example/sample/SampleApplication.java: -------------------------------------------------------------------------------- 1 | package swag.qrorder.sample.src.main.java.com.example.sample; 2 | 3 | import java.util.Scanner; 4 | 5 | public class SampleApplication { 6 | public static void main(String[] args) { 7 | CalculationRequest calculationRequest = new CalculationRequestReader().read(); 8 | long answer = new Calculator().calculate( 9 | calculationRequest.getNum1(), 10 | calculationRequest.getOperation(), 11 | calculationRequest.getNum2()); 12 | System.out.println(answer); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Junwon/sample/src/test/java/com/example/sample/CalculationRequestReaderTest.java: -------------------------------------------------------------------------------- 1 | package swag.qrorder.sample.src.test.java.com.example.sample; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.ByteArrayInputStream; 6 | 7 | import static org.junit.Assert.assertEquals; 8 | 9 | public class CalculationRequestReaderTest { 10 | @Test 11 | public void System_in으로_데이터를_읽어올_수_있다() { 12 | //given 13 | CalculationRequestReader reader = new CalculationRequestReader(); 14 | 15 | //when 16 | System.setIn(new ByteArrayInputStream("2 + 3".getBytes())); 17 | CalculationRequest result = reader.read(); 18 | 19 | //then 20 | assertEquals(2, result.getNum1()); 21 | assertEquals("+", result.getOperation()); 22 | assertEquals(3, result.getNum2()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/.idea/aws.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/.idea/checkstyle-idea.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10.15.0 5 | JavaOnly 6 | true 7 | 15 | 16 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar 3 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/README.md: -------------------------------------------------------------------------------- 1 | # Toy for test on spring! 2 | 3 | 해당 레포지토리는 테스트 코드 추가를 위한 토이 프로젝트 입니다. 4 | 코드가 얼마나 정상 동작하는지, 프로덕션에서 잘 동작하는지를 검증하지는 말아주세요. 5 | 스프링에 테스트를 넣는 과정을 보여드리기 위해 만들어진 레포지토리입니다. 6 | 당연히 완벽하지 않습니다. 7 | 8 | ## 실행하기 9 | 10 | ### 00. 바로 시작 11 | 12 | h2를 이용하여 `auto create table`을 하고 있기 때문에 바로 실행이 가능합니다. 13 | 14 | ### 01. 이메일 인증 15 | 16 | > 단 이 프로젝트는 사용자가 가입할 때 이메일 인증을 하기위해 메일을 발송하는 코드가 있습니다. 17 | 18 | 이메일이 제대로 발송되는지 확인해보고 싶으신 분들은 [해당 document 파일](./document/connect-mail-sender.md)을 따라해주세요. 19 | 관련된 자료는 라이브러리나 Gmail 정책에 따라 UI와 방법이 달라질 수 있습니다. 20 | 최신화 된 정보를 제공하지 않으니, 가급적 문서를 참조해주시고, contribution 해주시면 감사하겠습니다. 21 | 22 | ## 관리 도구로 바로가기 23 | 24 | - [h2-console](http://localhost:8080/h2-console) 25 | - [Openapi-doc](http://localhost:8080/swagger-ui.html) -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import io.swagger.v3.oas.annotations.OpenAPIDefinition; 4 | import io.swagger.v3.oas.annotations.info.Info; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | @SpringBootApplication 9 | @OpenAPIDefinition(info = @Info( 10 | title = "Toy project", 11 | version = "v1", 12 | description = "테스트 코드를 추가하기 위한 연습에 사용될 토이 프로젝트입니다" 13 | )) 14 | public class DemoApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(DemoApplication.class, args); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/common/controller/HealthCheckController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.controller; 2 | 3 | import io.swagger.v3.oas.annotations.tags.Tag; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @Tag(name = "헬스 체크") 9 | @RestController 10 | public class HealthCheckController { 11 | 12 | @GetMapping("/health_check.html") 13 | public ResponseEntity healthCheck() { 14 | return ResponseEntity 15 | .ok() 16 | .build(); 17 | } 18 | } -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/common/domain/exception/CertificationCodeNotMatchedException.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.domain.exception; 2 | 3 | public class CertificationCodeNotMatchedException extends RuntimeException { 4 | 5 | public CertificationCodeNotMatchedException() { 6 | super("자격 증명에 실패하였습니다."); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/common/domain/exception/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.domain.exception; 2 | 3 | public class ResourceNotFoundException extends RuntimeException { 4 | 5 | public ResourceNotFoundException(String datasource, long id) { 6 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 7 | } 8 | 9 | public ResourceNotFoundException(String datasource, String id) { 10 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/common/infrastructure/SystemClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.infrastructure; 2 | 3 | import com.example.demo.common.service.port.ClockHolder; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.time.Clock; 7 | 8 | @Component 9 | public class SystemClockHolder implements ClockHolder { 10 | @Override 11 | public long millis() { 12 | return Clock.systemUTC().millis(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/common/infrastructure/SystemUuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.infrastructure; 2 | 3 | import com.example.demo.common.service.port.UuidHolder; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.UUID; 7 | 8 | @Component 9 | public class SystemUuidHolder implements UuidHolder { 10 | @Override 11 | public String random() { 12 | return UUID.randomUUID().toString(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/common/service/port/ClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.service.port; 2 | 3 | public interface ClockHolder { 4 | 5 | long millis(); 6 | } 7 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/common/service/port/UuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.service.port; 2 | 3 | public interface UuidHolder { 4 | 5 | String random(); 6 | } 7 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/post/controller/port/PostService.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.post.controller.port; 2 | 3 | import com.example.demo.post.domain.Post; 4 | import com.example.demo.post.domain.PostCreate; 5 | import com.example.demo.post.domain.PostUpdate; 6 | 7 | public interface PostService { 8 | 9 | Post getById(long id); 10 | 11 | Post create(PostCreate postCreate); 12 | 13 | Post update(long id, PostUpdate postUpdate); 14 | } 15 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/post/domain/PostCreate.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class PostCreate { 9 | 10 | private final long writerId; 11 | private final String content; 12 | 13 | @Builder 14 | public PostCreate( 15 | @JsonProperty("writerId") long writerId, 16 | @JsonProperty("content") String content) { 17 | this.writerId = writerId; 18 | this.content = content; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/post/domain/PostUpdate.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class PostUpdate { 9 | 10 | private final String content; 11 | 12 | @Builder 13 | public PostUpdate( 14 | @JsonProperty("content") String content) { 15 | this.content = content; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/post/infrastructure/PostJpaRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.post.infrastructure; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface PostJpaRepository extends JpaRepository { 6 | 7 | } -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/post/infrastructure/PostRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.post.infrastructure; 2 | 3 | import java.util.Optional; 4 | 5 | import org.springframework.stereotype.Repository; 6 | 7 | import com.example.demo.post.domain.Post; 8 | import com.example.demo.post.service.port.PostRepository; 9 | 10 | import lombok.RequiredArgsConstructor; 11 | 12 | @Repository 13 | @RequiredArgsConstructor 14 | public class PostRepositoryImpl implements PostRepository { 15 | 16 | private final PostJpaRepository postJpaRepository; 17 | 18 | @Override 19 | public Optional findById(long id) { 20 | return postJpaRepository.findById(id).map(PostEntity::toModel); 21 | } 22 | 23 | @Override 24 | public Post save(Post post) { 25 | return postJpaRepository.save(PostEntity.from(post)).toModel(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/post/service/port/PostRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.post.service.port; 2 | 3 | import java.util.Optional; 4 | 5 | import com.example.demo.post.domain.Post; 6 | 7 | public interface PostRepository { 8 | Optional findById(long id); 9 | 10 | Post save(Post post); 11 | } 12 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/user/controller/port/UserService.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.controller.port; 2 | 3 | import com.example.demo.user.domain.User; 4 | import com.example.demo.user.domain.UserCreate; 5 | import com.example.demo.user.domain.UserUpdate; 6 | 7 | public interface UserService { 8 | 9 | User getByEmail(String email); 10 | 11 | User getById(long id); 12 | 13 | User create(UserCreate userCreate); 14 | 15 | User update(long id, UserUpdate userUpdate); 16 | 17 | void login(long id); 18 | 19 | void verifyEmail(long id, String certificationCode); 20 | } 21 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/user/domain/UserCreate.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class UserCreate { 9 | 10 | private final String email; 11 | private final String nickname; 12 | private final String address; 13 | 14 | @Builder 15 | public UserCreate( 16 | @JsonProperty("email") String email, 17 | @JsonProperty("nickname") String nickname, 18 | @JsonProperty("address") String address) { 19 | this.email = email; 20 | this.nickname = nickname; 21 | this.address = address; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/user/domain/UserStatus.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.domain; 2 | 3 | public enum UserStatus { 4 | PENDING, INACTIVE, ACTIVE 5 | } 6 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/user/domain/UserUpdate.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class UserUpdate { 9 | 10 | private final String nickname; 11 | private final String address; 12 | 13 | @Builder 14 | public UserUpdate( 15 | @JsonProperty("nickname") String nickname, 16 | @JsonProperty("address") String address) { 17 | this.nickname = nickname; 18 | this.address = address; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/user/infrastructure/MailSenderImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.infrastructure; 2 | 3 | import org.springframework.mail.SimpleMailMessage; 4 | import org.springframework.mail.javamail.JavaMailSender; 5 | import org.springframework.stereotype.Component; 6 | import com.example.demo.user.service.port.MailSender; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @Component 10 | @RequiredArgsConstructor 11 | public class MailSenderImpl implements MailSender { 12 | 13 | private final JavaMailSender javaMailSender; 14 | 15 | @Override 16 | public void send(String email, String title, String content) { 17 | SimpleMailMessage message = new SimpleMailMessage(); 18 | message.setTo(email); 19 | message.setSubject(title); 20 | message.setText(content); 21 | javaMailSender.send(message); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/user/infrastructure/UserJpaRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.infrastructure; 2 | 3 | import com.example.demo.user.domain.UserStatus; 4 | import java.util.Optional; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | public interface UserJpaRepository extends JpaRepository { 8 | 9 | Optional findByIdAndStatus(long id, UserStatus userStatus); 10 | 11 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 12 | } 13 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/user/service/port/MailSender.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.service.port; 2 | 3 | public interface MailSender { 4 | 5 | void send(String email, String title, String content); 6 | } 7 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/java/com/example/demo/user/service/port/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.service.port; 2 | 3 | import java.util.Optional; 4 | 5 | import com.example.demo.user.domain.User; 6 | import com.example.demo.user.domain.UserStatus; 7 | 8 | public interface UserRepository { 9 | 10 | User getById(long id); 11 | 12 | Optional findById(long id); 13 | 14 | Optional findByIdAndStatus(long id, UserStatus userStatus); 15 | 16 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 17 | 18 | User save(User userEntity); 19 | } 20 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.h2.console.enabled=true 2 | spring.h2.console.path=/h2-console 3 | spring.datasource.url=jdbc:h2:~/mem-data; 4 | spring.datasource.driverClassName=org.h2.Driver 5 | spring.datasource.username=sa 6 | spring.datasource.password= 7 | spring.jpa.hibernate.ddl-auto=create 8 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 9 | springdoc.swagger-ui.path=/swagger-ui.html 10 | 11 | spring.mail.host=smtp.gmail.com 12 | spring.mail.port=587 13 | spring.mail.username=${MAIL_USERNAME} 14 | spring.mail.password=${MAIL_APPLICATION_PASSWORD} 15 | spring.mail.properties.mail.smtp.auth=true 16 | spring.mail.properties.mail.smtp.timeout=5000 17 | spring.mail.properties.mail.smtp.starttls.enable=true -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/test/java/com/example/demo/mock/FakeMailSender.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.mock; 2 | 3 | import com.example.demo.user.service.port.MailSender; 4 | 5 | public class FakeMailSender implements MailSender { 6 | 7 | public String email; 8 | public String title; 9 | public String content; 10 | 11 | @Override 12 | public void send(String email, String title, String content) { 13 | this.email = email; 14 | this.title = title; 15 | this.content = content; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/test/java/com/example/demo/mock/TestClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.mock; 2 | 3 | import com.example.demo.common.service.port.ClockHolder; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @RequiredArgsConstructor 7 | public class TestClockHolder implements ClockHolder { 8 | 9 | private final long millis; 10 | 11 | @Override 12 | public long millis() { 13 | return millis; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/test/java/com/example/demo/mock/TestUuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.mock; 2 | 3 | import com.example.demo.common.service.port.UuidHolder; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @RequiredArgsConstructor 7 | public class TestUuidHolder implements UuidHolder { 8 | 9 | private final String uuid; 10 | 11 | @Override 12 | public String random() { 13 | return uuid; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/test/resources/sql/delete-all-data.sql: -------------------------------------------------------------------------------- 1 | delete from `posts` where 1; 2 | delete from `users` where 1; -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/test/resources/sql/post-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) 4 | values (1, 'helloworld', 1678530673958, 0, 1); -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/test/resources/sql/post-create-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/test/resources/sql/post-service-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 4 | values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); 5 | insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) 6 | values (1, 'helloworld', 1678530673958, 0, 1); -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/test/resources/sql/user-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 4 | values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/test/resources/sql/user-repository-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/test/resources/sql/user-service-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 4 | values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/src/test/resources/test-application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1 2 | spring.datasource.driverClassName=org.h2.Driver 3 | spring.datasource.username=sa 4 | spring.datasource.password= 5 | spring.h2.console.enabled=true 6 | 7 | spring.jpa.hibernate.dialect=org.hibernate.dialect.MariaDBDialect 8 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 9 | spring.jpa.hibernate.ddl-auto=create-drop -------------------------------------------------------------------------------- /Junwon/test-code-with-architecture-main/target/classes/application.properties: -------------------------------------------------------------------------------- 1 | spring.h2.console.enabled=true 2 | spring.h2.console.path=/h2-console 3 | spring.datasource.url=jdbc:h2:~/mem-data; 4 | spring.datasource.driverClassName=org.h2.Driver 5 | spring.datasource.username=sa 6 | spring.datasource.password= 7 | spring.jpa.hibernate.ddl-auto=create 8 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 9 | springdoc.swagger-ui.path=/swagger-ui.html 10 | 11 | spring.mail.host=smtp.gmail.com 12 | spring.mail.port=587 13 | spring.mail.username=${MAIL_USERNAME} 14 | spring.mail.password=${MAIL_APPLICATION_PASSWORD} 15 | spring.mail.properties.mail.smtp.auth=true 16 | spring.mail.properties.mail.smtp.timeout=5000 17 | spring.mail.properties.mail.smtp.starttls.enable=true -------------------------------------------------------------------------------- /Nahyeon/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | -------------------------------------------------------------------------------- /Nahyeon/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Nahyeon/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Nahyeon/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /Nahyeon/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'nahyeon' 2 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/NahyeonApplication.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | import io.swagger.v3.oas.annotations.OpenAPIDefinition; 7 | import io.swagger.v3.oas.annotations.info.Info; 8 | 9 | @SpringBootApplication 10 | @OpenAPIDefinition(info = @Info( 11 | title = "Toy project", 12 | version = "v1", 13 | description = "테스트 코드를 추가하기 위한 연습에 사용될 토이 프로젝트입니다" 14 | )) 15 | public class NahyeonApplication { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(NahyeonApplication.class, args); 19 | } 20 | } -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/common/controller/HealthCheckController.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.common.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import io.swagger.v3.oas.annotations.tags.Tag; 8 | 9 | @Tag(name = "헬스 체크") 10 | @RestController 11 | public class HealthCheckController { 12 | 13 | @GetMapping("/health_check.html") 14 | public ResponseEntity healthCheck() { 15 | return ResponseEntity.ok().build(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/common/domain/exception/CertificationCodeNotMatchedException.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.common.domain.exception; 2 | 3 | public class CertificationCodeNotMatchedException extends RuntimeException { 4 | 5 | public CertificationCodeNotMatchedException() { 6 | super("자격 증명에 실패하였습니다."); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/common/domain/exception/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.common.domain.exception; 2 | 3 | public class ResourceNotFoundException extends RuntimeException { 4 | 5 | public ResourceNotFoundException(String dataSource, long id) { 6 | super(dataSource + "에서 ID " + id + "를 찾을 수 없습니다."); 7 | } 8 | 9 | public ResourceNotFoundException(String dataSource, String email) { 10 | super(dataSource + "에서 ID " + email + "를 찾을 수 없습니다."); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/common/infrastructure/SystemClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.common.infrastructure; 2 | 3 | import java.time.Clock; 4 | 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.depromeet.nahyeon.common.service.port.ClockHolder; 8 | 9 | @Component 10 | public class SystemClockHolder implements ClockHolder { 11 | 12 | @Override 13 | public long millis() { 14 | return Clock.systemUTC().millis(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/common/infrastructure/SystemUuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.common.infrastructure; 2 | 3 | import java.util.UUID; 4 | 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.depromeet.nahyeon.common.service.port.UuidHolder; 8 | 9 | @Component 10 | public class SystemUuidHolder implements UuidHolder { 11 | @Override 12 | public String random() { 13 | return UUID.randomUUID().toString(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/common/service/port/ClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.common.service.port; 2 | 3 | public interface ClockHolder { 4 | 5 | long millis(); 6 | } 7 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/common/service/port/UuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.common.service.port; 2 | 3 | public interface UuidHolder { 4 | 5 | String random(); 6 | } 7 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/post/controller/port/PostService.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.post.controller.port; 2 | 3 | import com.depromeet.nahyeon.post.domain.Post; 4 | import com.depromeet.nahyeon.post.domain.PostCreate; 5 | import com.depromeet.nahyeon.post.domain.PostUpdate; 6 | 7 | public interface PostService { 8 | 9 | Post getById(long id); 10 | 11 | Post create(PostCreate postCreate); 12 | 13 | Post update(long id, PostUpdate postUpdate); 14 | } 15 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/post/controller/response/PostResponse.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.post.controller.response; 2 | 3 | import com.depromeet.nahyeon.post.domain.Post; 4 | import com.depromeet.nahyeon.user.controller.response.UserResponse; 5 | 6 | import lombok.Builder; 7 | import lombok.Getter; 8 | 9 | @Getter 10 | @Builder 11 | public class PostResponse { 12 | 13 | private Long id; 14 | private String content; 15 | private Long createdAt; 16 | private Long modifiedAt; 17 | private UserResponse writer; 18 | 19 | public static PostResponse from(Post post) { 20 | return PostResponse.builder() 21 | .id(post.getId()) 22 | .content(post.getContent()) 23 | .createdAt(post.getCreatedAt()) 24 | .modifiedAt(post.getModifiedAt()) 25 | .writer(UserResponse.from(post.getWriter())) 26 | .build(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/post/domain/PostCreate.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class PostCreate { 10 | 11 | private final long writerId; 12 | private final String content; 13 | 14 | @Builder 15 | public PostCreate( 16 | @JsonProperty("writerId") long writerId, 17 | @JsonProperty("content") String content 18 | ) { 19 | this.writerId = writerId; 20 | this.content = content; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/post/domain/PostUpdate.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class PostUpdate { 10 | 11 | private final String content; 12 | 13 | @Builder 14 | public PostUpdate( 15 | @JsonProperty("content") String content 16 | ) { 17 | this.content = content; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/post/infrastructure/PostJpaRepository.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.post.infrastructure; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface PostJpaRepository extends JpaRepository { 6 | } 7 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/post/infrastructure/PostRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.post.infrastructure; 2 | 3 | import java.util.Optional; 4 | 5 | import org.springframework.stereotype.Repository; 6 | 7 | import com.depromeet.nahyeon.post.domain.Post; 8 | import com.depromeet.nahyeon.post.service.port.PostRepository; 9 | 10 | import lombok.RequiredArgsConstructor; 11 | 12 | @Repository 13 | @RequiredArgsConstructor 14 | public class PostRepositoryImpl implements PostRepository { 15 | 16 | private final PostJpaRepository postJpaRepository; 17 | 18 | @Override 19 | public Optional findById(long id) { 20 | return postJpaRepository.findById(id).map(PostEntity::toModel); 21 | } 22 | 23 | @Override 24 | public Post save(Post post) { 25 | return postJpaRepository.save(PostEntity.fromModel(post)).toModel(); 26 | } 27 | } -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/post/service/port/PostRepository.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.post.service.port; 2 | 3 | import java.util.Optional; 4 | 5 | import com.depromeet.nahyeon.post.domain.Post; 6 | 7 | public interface PostRepository { 8 | 9 | Optional findById(long id); 10 | 11 | Post save(Post post); 12 | } 13 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/user/controller/port/UserService.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.user.controller.port; 2 | 3 | import com.depromeet.nahyeon.user.domain.User; 4 | import com.depromeet.nahyeon.user.domain.UserCreate; 5 | import com.depromeet.nahyeon.user.domain.UserUpdate; 6 | 7 | public interface UserService { 8 | 9 | User getById(long id); 10 | 11 | User getByEmail(String email); 12 | 13 | User update(long id, UserUpdate userUpdate); 14 | 15 | User create(UserCreate userCreate); 16 | 17 | void login(long id); 18 | 19 | void verifyEmail(long id, String certificationCode); 20 | } 21 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/user/controller/response/UserResponse.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.user.controller.response; 2 | 3 | import com.depromeet.nahyeon.user.domain.User; 4 | import com.depromeet.nahyeon.user.domain.UserStatus; 5 | 6 | import lombok.Builder; 7 | import lombok.Getter; 8 | 9 | @Getter 10 | @Builder 11 | public class UserResponse { 12 | 13 | private Long id; 14 | private String email; 15 | private String nickname; 16 | private UserStatus status; 17 | private Long lastLoginAt; 18 | 19 | public static UserResponse from(User user) { 20 | return UserResponse.builder() 21 | .id(user.getId()) 22 | .email(user.getEmail()) 23 | .nickname(user.getNickname()) 24 | .status(user.getStatus()) 25 | .lastLoginAt(user.getLastLoginAt()) 26 | .build(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/user/domain/UserCreate.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class UserCreate { 10 | 11 | private final String email; 12 | private final String nickname; 13 | private final String address; 14 | 15 | @Builder 16 | public UserCreate( 17 | @JsonProperty("email") String email, 18 | @JsonProperty("nickname") String nickname, 19 | @JsonProperty("address") String address 20 | ) { 21 | this.email = email; 22 | this.nickname = nickname; 23 | this.address = address; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/user/domain/UserStatus.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.user.domain; 2 | 3 | public enum UserStatus { 4 | PENDING, INACTIVE, ACTIVE 5 | } -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/user/domain/UserUpdate.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class UserUpdate { 10 | 11 | private final String nickname; 12 | private final String address; 13 | 14 | @Builder 15 | public UserUpdate( 16 | @JsonProperty("nickname") String nickname, 17 | @JsonProperty("address") String address 18 | ) { 19 | this.nickname = nickname; 20 | this.address = address; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/user/infrastructure/MailSenderImpl.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.user.infrastructure; 2 | 3 | import org.springframework.mail.SimpleMailMessage; 4 | import org.springframework.mail.javamail.JavaMailSender; 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.depromeet.nahyeon.user.service.port.MailSender; 8 | 9 | import lombok.RequiredArgsConstructor; 10 | 11 | @Component 12 | @RequiredArgsConstructor 13 | public class MailSenderImpl implements MailSender { 14 | 15 | private final JavaMailSender mailSender; 16 | 17 | @Override 18 | public void send(String email, String title, String content) { 19 | SimpleMailMessage message = new SimpleMailMessage(); 20 | message.setTo(email); 21 | message.setSubject(title); 22 | message.setText(content); 23 | mailSender.send(message); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/user/infrastructure/UserJpaRepository.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.user.infrastructure; 2 | 3 | import java.util.Optional; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import com.depromeet.nahyeon.user.domain.UserStatus; 8 | 9 | public interface UserJpaRepository extends JpaRepository { 10 | 11 | Optional findByIdAndStatus(long id, UserStatus status); 12 | 13 | Optional findByEmailAndStatus(String email, UserStatus status); 14 | } 15 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/user/service/port/MailSender.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.user.service.port; 2 | 3 | public interface MailSender { 4 | 5 | void send(String email, String title, String content); 6 | } 7 | -------------------------------------------------------------------------------- /Nahyeon/src/main/java/com/depromeet/nahyeon/user/service/port/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.user.service.port; 2 | 3 | import java.util.Optional; 4 | 5 | import com.depromeet.nahyeon.user.domain.User; 6 | import com.depromeet.nahyeon.user.domain.UserStatus; 7 | 8 | public interface UserRepository { 9 | 10 | User getById(long id); 11 | 12 | Optional findById(long id); 13 | 14 | Optional findByIdAndStatus(long id, UserStatus status); 15 | 16 | Optional findByEmailAndStatus(String email, UserStatus status); 17 | 18 | User save(User user); 19 | } -------------------------------------------------------------------------------- /Nahyeon/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: nahyeon 4 | 5 | datasource: 6 | url: jdbc:h2:tcp://localhost/~/testdb 7 | driver-class-name: org.h2.Driver 8 | username: sa 9 | 10 | jpa: 11 | hibernate: 12 | ddl-auto: create 13 | properties: 14 | hibernate: 15 | format_sql: true 16 | use_sql_comments: true 17 | database-platform: org.hibernate.dialect.H2Dialect 18 | 19 | h2: 20 | console: 21 | enabled: true 22 | path: /h2-console 23 | 24 | mail: 25 | host: smtp.gmail.com 26 | port: 587 27 | username: ${MAIL_USERNAME} 28 | password: ${MAIL_PASSWORD} 29 | properties: 30 | mail.smtp: 31 | auth: true 32 | timeout: 5000 33 | starttls: 34 | enable: true -------------------------------------------------------------------------------- /Nahyeon/src/test/java/com/depromeet/nahyeon/NahyeonApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class NahyeonApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Nahyeon/src/test/java/com/depromeet/nahyeon/mock/FakeMailSender.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.mock; 2 | 3 | import com.depromeet.nahyeon.user.service.port.MailSender; 4 | 5 | public class FakeMailSender implements MailSender { 6 | 7 | public String email; 8 | public String title; 9 | public String content; 10 | 11 | @Override 12 | public void send(String email, String title, String content) { 13 | this.email = email; 14 | this.title = title; 15 | this.content = content; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Nahyeon/src/test/java/com/depromeet/nahyeon/mock/TestClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.mock; 2 | 3 | import com.depromeet.nahyeon.common.service.port.ClockHolder; 4 | 5 | import lombok.RequiredArgsConstructor; 6 | 7 | @RequiredArgsConstructor 8 | public class TestClockHolder implements ClockHolder { 9 | 10 | private final long millis; 11 | 12 | @Override 13 | public long millis() { 14 | return millis; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Nahyeon/src/test/java/com/depromeet/nahyeon/mock/TestUuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.nahyeon.mock; 2 | 3 | import com.depromeet.nahyeon.common.service.port.UuidHolder; 4 | 5 | import lombok.RequiredArgsConstructor; 6 | 7 | @RequiredArgsConstructor 8 | public class TestUuidHolder implements UuidHolder { 9 | 10 | private final String uuid; 11 | 12 | @Override 13 | public String random() { 14 | return uuid; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Nahyeon/src/test/resources/sql/delete-all-data.sql: -------------------------------------------------------------------------------- 1 | delete from `posts` where 1; 2 | delete from `users` where 1; -------------------------------------------------------------------------------- /Nahyeon/src/test/resources/sql/post-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'nahyeonee99@gmail.com', 'nahyeonee99', 'Seoul', 'aaaaaaaa-aaaaaaaa-aaaaaaaa', 'ACTIVE', 0); 3 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 4 | values (2, 'nahyeonee100@gmail.com', 'nahyeonee100', 'Seoul', 'aaaaaaaa-aaaaaaaa-aaaaaaab', 'PENDING', 0); 5 | insert into `posts`(`id`, `user_id`, `content`, `created_at`, `modified_at`) 6 | values (1, 1, 'test 1', 0, 1); 7 | insert into `posts`(`id`, `user_id`, `content`, `created_at`, `modified_at`) 8 | values (2, 1, 'test 2', 0, 1); 9 | insert into `posts`(`id`, `user_id`, `content`, `created_at`, `modified_at`) 10 | values (3, 1, 'test 3', 0, 1); -------------------------------------------------------------------------------- /Nahyeon/src/test/resources/sql/post-create-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'nahyeonee99@gmail.com', 'nahyeonee99', 'Seoul', 'aaaaaaaa-aaaaaaaa-aaaaaaaa', 'ACTIVE', 0); 3 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 4 | values (2, 'nahyeonee100@gmail.com', 'nahyeonee100', 'Seoul', 'aaaaaaaa-aaaaaaaa-aaaaaaab', 'PENDING', 0); -------------------------------------------------------------------------------- /Nahyeon/src/test/resources/sql/post-service-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'nahyeonee99@gmail.com', 'nahyeonee99', 'Seoul', 'aaaaaaaa-aaaaaaaa-aaaaaaaa', 'ACTIVE', 0); 3 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 4 | values (2, 'nahyeonee100@gmail.com', 'nahyeonee100', 'Seoul', 'aaaaaaaa-aaaaaaaa-aaaaaaab', 'PENDING', 0); 5 | insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) 6 | values (1, 'helloworld', 0, 1, 1); -------------------------------------------------------------------------------- /Nahyeon/src/test/resources/sql/user-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'nahyeonee99@gmail.com', 'nahyeonee99', 'Seoul', 'aaaaaaaa-aaaaaaaa-aaaaaaaa', 'ACTIVE', 0); 3 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 4 | values (2, 'nahyeonee100@gmail.com', 'nahyeonee100', 'Seoul', 'aaaaaaaa-aaaaaaaa-aaaaaaab', 'PENDING', 0); -------------------------------------------------------------------------------- /Nahyeon/src/test/resources/sql/user-repository-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'nahyeonee99@gmail.com', 'nahyeonee99', 'Seoul', 'aaaaaaaa-aaaaaaaa-aaaaaaaa', 'ACTIVE', 0); -------------------------------------------------------------------------------- /Nahyeon/src/test/resources/sql/user-service-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'nahyeonee99@gmail.com', 'nahyeonee99', 'Seoul', 'aaaaaaaa-aaaaaaaa-aaaaaaaa', 'ACTIVE', 0); 3 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 4 | values (2, 'nahyeonee100@gmail.com', 'nahyeonee100', 'Seoul', 'aaaaaaaa-aaaaaaaa-aaaaaaab', 'PENDING', 0); -------------------------------------------------------------------------------- /Nahyeon/src/test/resources/test-application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: nahyeon 4 | 5 | datasource: 6 | url: jdbc:h2:tcp://localhost/~/testdb;mode=mysql 7 | driver-class-name: org.h2.Driver 8 | username: sa 9 | 10 | jpa: 11 | hibernate: 12 | ddl-auto: create 13 | properties: 14 | hibernate: 15 | format_sql: true 16 | use_sql_comments: true 17 | database-platform: org.hibernate.dialect.H2Dialect 18 | 19 | h2: 20 | console: 21 | enabled: true 22 | path: /h2-console 23 | 24 | mail: 25 | host: smtp.gmail.com 26 | port: 587 27 | username: ${MAIL_USERNAME} 28 | password: ${MAIL_PASSWORD} 29 | properties: 30 | mail.smtp: 31 | auth: true 32 | timeout: 5000 33 | starttls: 34 | enable: true -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 15th-Spring-Test-Study 2 | 15기 Java/Spring 테스트 코드 스터디 3 | -------------------------------------------------------------------------------- /Wonchae/sample/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /Wonchae/sample/src/main/java/com/example/sample/BadRequestException.java: -------------------------------------------------------------------------------- 1 | package com.example.sample; 2 | 3 | public class BadRequestException extends RuntimeException { 4 | public BadRequestException() { 5 | super("Invalid input size, you must input 3 length"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Wonchae/sample/src/main/java/com/example/sample/CalculationRequestReader.java: -------------------------------------------------------------------------------- 1 | package com.example.sample; 2 | 3 | import java.util.Scanner; 4 | 5 | public class CalculationRequestReader { 6 | public CalculationRequst read() { 7 | Scanner scanner = new Scanner(System.in); 8 | System.out.println("Enter two numbers and an operator (e.g 1 + 2):"); 9 | String result = scanner.nextLine(); 10 | String[] parts = result.split(" "); 11 | return new CalculationRequst(parts); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Wonchae/sample/src/main/java/com/example/sample/Calculator.java: -------------------------------------------------------------------------------- 1 | package com.example.sample; 2 | 3 | public class Calculator { 4 | public long calculate(long num1, String operator, long num2) { 5 | return switch (operator) { 6 | case "+" -> num1 + num2; 7 | case "-" -> num1 - num2; 8 | case "*" -> num1 * num2; 9 | case "/" -> num1 / num2; 10 | default -> throw new InvalidOperatorException(); 11 | }; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Wonchae/sample/src/main/java/com/example/sample/InvalidOperatorException.java: -------------------------------------------------------------------------------- 1 | package com.example.sample; 2 | 3 | public class InvalidOperatorException extends RuntimeException { 4 | public InvalidOperatorException() { 5 | super("Invalid operator, you need to choose one of (+,-,*,/)"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Wonchae/sample/src/main/java/com/example/sample/SampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.sample; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | import java.util.Scanner; 7 | 8 | @SpringBootApplication 9 | public class SampleApplication { 10 | 11 | public static void main(String[] args) { 12 | CalculationRequst calculationRequst = new CalculationRequestReader().read(); 13 | long answer = new Calculator().calculate( 14 | calculationRequst.getNum1(), 15 | calculationRequst.getOperator(), 16 | calculationRequst.getNum2() 17 | ); 18 | System.out.println(answer); 19 | // SpringApplication.run(SampleApplication.class, args); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Wonchae/sample/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=sample 2 | -------------------------------------------------------------------------------- /Wonchae/sample/src/test/java/com/example/sample/CalculationRequestReaderTest.java: -------------------------------------------------------------------------------- 1 | package com.example.sample; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.io.ByteArrayInputStream; 7 | 8 | public class CalculationRequestReaderTest { 9 | @Test 10 | public void System_in으로_데이터를_읽어들일_수_있다() { 11 | // given 12 | CalculationRequestReader calculationRequestReader = new CalculationRequestReader(); 13 | 14 | // when 15 | System.setIn(new ByteArrayInputStream("2 + 3".getBytes())); 16 | CalculationRequst result = calculationRequestReader.read(); 17 | 18 | // then 19 | Assertions.assertEquals(2, result.getNum1()); 20 | Assertions.assertEquals("+", result.getOperator()); 21 | Assertions.assertEquals(3, result.getNum2()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Wonchae/sample/src/test/java/com/example/sample/SampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.sample; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SampleApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Wonchae/test-code-with-architecture/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar 3 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/README.md: -------------------------------------------------------------------------------- 1 | # Toy for test on spring! 2 | 3 | 해당 레포지토리는 테스트 코드 추가를 위한 토이 프로젝트 입니다. 4 | 코드가 얼마나 정상 동작하는지, 프로덕션에서 잘 동작하는지를 검증하지는 말아주세요. 5 | 스프링에 테스트를 넣는 과정을 보여드리기 위해 만들어진 레포지토리입니다. 6 | 당연히 완벽하지 않습니다. 7 | 8 | ## 실행하기 9 | 10 | ### 00. 바로 시작 11 | 12 | h2를 이용하여 `auto create table`을 하고 있기 때문에 바로 실행이 가능합니다. 13 | 14 | ### 01. 이메일 인증 15 | 16 | > 단 이 프로젝트는 사용자가 가입할 때 이메일 인증을 하기위해 메일을 발송하는 코드가 있습니다. 17 | 18 | 이메일이 제대로 발송되는지 확인해보고 싶으신 분들은 [해당 document 파일](./document/connect-mail-sender.md)을 따라해주세요. 19 | 관련된 자료는 라이브러리나 Gmail 정책에 따라 UI와 방법이 달라질 수 있습니다. 20 | 최신화 된 정보를 제공하지 않으니, 가급적 문서를 참조해주시고, contribution 해주시면 감사하겠습니다. 21 | 22 | ## 관리 도구로 바로가기 23 | 24 | - [h2-console](http://localhost:8080/h2-console) 25 | - [Openapi-doc](http://localhost:8080/swagger-ui.html) -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/document/connect-mail-sender.md: -------------------------------------------------------------------------------- 1 | # 구글 이메일 발송하기 2 | 3 | 1. 메일 발송을 위한 계정 세팅 변경 4 | ![01.메일 발송을 위한 계정 세팅 변경](./resources/01.mail-settings.png) 5 | 2. 계정에 애플리케이션 접근을 위한 패스워드 생성 6 | ![012.계정에 애플리케이션 접근을 위한 패스워드 생성](./resources/02.mail-settings.png) 7 | 3. 메일을 선택 8 | ![03.메일을 선택](./resources/03.mail-settings.png) 9 | 4. 기타를 선택 10 | ![04.기타를 선택](./resources/04.mail-settings.png) 11 | 5. 패스워드에 이름을 작성 12 | ![05.패스워드에 이름을 작성](./resources/05.mail-settings.png) 13 | 6. 패스워드를 복사 14 | ![06.패스워드를 복사](./resources/06.mail-settings.png) 15 | 7. `Environment variables`에 다음과 같이 입력해주세요 16 | ![07.`Environment variables`에 다음과 같이 입력해주세요](./resources/07.mail-settings.png) 17 | > ex. MAIL_USERNAME=test;MAIL_APPLICATION_PASSWORD=aaaabbbbccccdddd 18 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/document/resources/01.mail-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Wonchae/test-code-with-architecture/document/resources/01.mail-settings.png -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/document/resources/02.mail-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Wonchae/test-code-with-architecture/document/resources/02.mail-settings.png -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/document/resources/03.mail-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Wonchae/test-code-with-architecture/document/resources/03.mail-settings.png -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/document/resources/04.mail-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Wonchae/test-code-with-architecture/document/resources/04.mail-settings.png -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/document/resources/05.mail-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Wonchae/test-code-with-architecture/document/resources/05.mail-settings.png -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/document/resources/06.mail-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Wonchae/test-code-with-architecture/document/resources/06.mail-settings.png -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/document/resources/07.mail-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Wonchae/test-code-with-architecture/document/resources/07.mail-settings.png -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import io.swagger.v3.oas.annotations.OpenAPIDefinition; 4 | import io.swagger.v3.oas.annotations.info.Info; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | 8 | @SpringBootApplication 9 | @OpenAPIDefinition(info = @Info( 10 | title = "Toy project", 11 | version = "v1", 12 | description = "테스트 코드를 추가하기 위한 연습에 사용될 토이 프로젝트입니다" 13 | )) 14 | public class DemoApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(DemoApplication.class, args); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/common/controller/HealthCheckController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.controller; 2 | 3 | import io.swagger.v3.oas.annotations.tags.Tag; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @Tag(name = "헬스 체크") 9 | @RestController 10 | public class HealthCheckController { 11 | 12 | @GetMapping("/health_check.html") 13 | public ResponseEntity healthCheck() { 14 | return ResponseEntity 15 | .ok() 16 | .build(); 17 | } 18 | } -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/common/domain/exception/CertificationCodeNotMatchedException.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.domain.exception; 2 | 3 | public class CertificationCodeNotMatchedException extends RuntimeException { 4 | 5 | public CertificationCodeNotMatchedException() { 6 | super("자격 증명에 실패하였습니다."); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/common/domain/exception/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.domain.exception; 2 | 3 | public class ResourceNotFoundException extends RuntimeException { 4 | 5 | public ResourceNotFoundException(String datasource, long id) { 6 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 7 | } 8 | 9 | public ResourceNotFoundException(String datasource, String id) { 10 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/common/infrastructure/SystemClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.infrastructure; 2 | 3 | import com.example.demo.common.service.port.ClockHolder; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.time.Clock; 7 | 8 | @Component 9 | public class SystemClockHolder implements ClockHolder { 10 | @Override 11 | public long millis() { 12 | return Clock.systemUTC().millis(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/common/infrastructure/SystemUuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.infrastructure; 2 | 3 | import com.example.demo.common.service.port.UuidHolder; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.UUID; 7 | 8 | @Component 9 | public class SystemUuidHolder implements UuidHolder { 10 | @Override 11 | public String random() { 12 | return UUID.randomUUID().toString(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/common/service/port/ClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.service.port; 2 | 3 | public interface ClockHolder { 4 | long millis(); 5 | } 6 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/common/service/port/UuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.common.service.port; 2 | 3 | public interface UuidHolder { 4 | String random(); 5 | } 6 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/post/controller/port/PostService.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.post.controller.port; 2 | 3 | import com.example.demo.post.domain.Post; 4 | import com.example.demo.post.domain.PostCreate; 5 | import com.example.demo.post.domain.PostUpdate; 6 | 7 | public interface PostService { 8 | Post getById(long id); 9 | Post create(PostCreate postCreate); 10 | Post update(long id, PostUpdate postUpdate); 11 | } 12 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/post/domain/PostCreate.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class PostCreate { 9 | 10 | private final long writerId; 11 | private final String content; 12 | 13 | @Builder 14 | public PostCreate( 15 | @JsonProperty("writerId") long writerId, 16 | @JsonProperty("content") String content) { 17 | this.writerId = writerId; 18 | this.content = content; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/post/domain/PostUpdate.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class PostUpdate { 9 | 10 | private final String content; 11 | 12 | @Builder 13 | public PostUpdate( 14 | @JsonProperty("content") String content) { 15 | this.content = content; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/post/infrastructure/PostJpaRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.post.infrastructure; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface PostJpaRepository extends JpaRepository { 6 | 7 | } -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/post/service/port/PostRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.post.service.port; 2 | 3 | import com.example.demo.post.domain.Post; 4 | import com.example.demo.post.infrastructure.PostEntity; 5 | 6 | import java.util.Optional; 7 | 8 | public interface PostRepository { 9 | Optional findById(long id); 10 | 11 | Post save(Post post); 12 | } 13 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/user/controller/port/UserService.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.controller.port; 2 | 3 | import com.example.demo.user.domain.User; 4 | import com.example.demo.user.domain.UserCreate; 5 | import com.example.demo.user.domain.UserUpdate; 6 | 7 | public interface UserService { 8 | User getByEmail(String email); 9 | User getById(long id); 10 | User create(UserCreate userCreate); 11 | User update(long id, UserUpdate userUpdate); 12 | void login(long id); 13 | void verifyEmail(long id, String certificationCode); 14 | } 15 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/user/domain/UserCreate.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class UserCreate { 9 | 10 | private final String email; 11 | private final String nickname; 12 | private final String address; 13 | 14 | @Builder 15 | public UserCreate( 16 | @JsonProperty("email") String email, 17 | @JsonProperty("nickname") String nickname, 18 | @JsonProperty("address") String address) { 19 | this.email = email; 20 | this.nickname = nickname; 21 | this.address = address; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/user/domain/UserStatus.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.domain; 2 | 3 | public enum UserStatus { 4 | PENDING, INACTIVE, ACTIVE 5 | } 6 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/user/domain/UserUpdate.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | public class UserUpdate { 9 | 10 | private final String nickname; 11 | private final String address; 12 | 13 | @Builder 14 | public UserUpdate( 15 | @JsonProperty("nickname") String nickname, 16 | @JsonProperty("address") String address) { 17 | this.nickname = nickname; 18 | this.address = address; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/user/infrastructure/UserJpaRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.infrastructure; 2 | 3 | import com.example.demo.user.domain.UserStatus; 4 | import java.util.Optional; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | public interface UserJpaRepository extends JpaRepository { 9 | 10 | Optional findByIdAndStatus(long id, UserStatus userStatus); 11 | 12 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 13 | } 14 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/user/service/port/MailSender.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.service.port; 2 | 3 | public interface MailSender { 4 | void send(String email, String title, String content); 5 | } 6 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/java/com/example/demo/user/service/port/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.user.service.port; 2 | 3 | import com.example.demo.user.domain.User; 4 | import com.example.demo.user.domain.UserStatus; 5 | import com.example.demo.user.infrastructure.UserEntity; 6 | 7 | import java.util.Optional; 8 | 9 | public interface UserRepository { 10 | 11 | User getById(long id); 12 | 13 | Optional findById(long id); 14 | 15 | Optional findByIdAndStatus(long id, UserStatus userStatus); 16 | 17 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 18 | 19 | User save(User user); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.h2.console.enabled=true 2 | spring.h2.console.path=/h2-console 3 | spring.datasource.url=jdbc:h2:~/mem-data; 4 | spring.datasource.driverClassName=org.h2.Driver 5 | spring.datasource.username=sa 6 | spring.datasource.password= 7 | spring.jpa.hibernate.ddl-auto=create 8 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 9 | springdoc.swagger-ui.path=/swagger-ui.html 10 | 11 | spring.mail.host=smtp.gmail.com 12 | spring.mail.port=587 13 | spring.mail.username=${MAIL_USERNAME} 14 | spring.mail.password=${MAIL_APPLICATION_PASSWORD} 15 | spring.mail.properties.mail.smtp.auth=true 16 | spring.mail.properties.mail.smtp.timeout=5000 17 | spring.mail.properties.mail.smtp.starttls.enable=true -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/test/java/com/example/demo/mock/FakeMailSender.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.mock; 2 | 3 | import com.example.demo.user.service.port.MailSender; 4 | 5 | public class FakeMailSender implements MailSender { 6 | 7 | public String email; 8 | public String title; 9 | public String content; 10 | 11 | @Override 12 | public void send(String email, String title, String content) { 13 | this.email = email; 14 | this.title = title; 15 | this.content = content; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/test/java/com/example/demo/mock/TestClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.mock; 2 | 3 | import com.example.demo.common.service.port.ClockHolder; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @RequiredArgsConstructor 7 | public class TestClockHolder implements ClockHolder { 8 | private final long millis; 9 | 10 | @Override 11 | public long millis() { 12 | return millis; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/test/java/com/example/demo/mock/TestUuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.mock; 2 | 3 | import com.example.demo.common.service.port.UuidHolder; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @RequiredArgsConstructor 7 | public class TestUuidHolder implements UuidHolder { 8 | private final String uuid; 9 | 10 | @Override 11 | public String random() { 12 | return uuid; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/test/resources/sql/delete-all-data.sql: -------------------------------------------------------------------------------- 1 | 2 | delete from `posts` where 1; 3 | delete from `users` where 1; 4 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/test/resources/sql/post-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 3 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 4 | insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) 5 | values (1, 'helloworld', 1678530673958, 0, 1); -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/test/resources/sql/post-create-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 3 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/test/resources/sql/post-service-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 3 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); 6 | insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) 7 | values (1, 'helloworld', 1678530673958, 0, 1); -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/test/resources/sql/user-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 3 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); 6 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/test/resources/sql/user-repository-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 3 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 4 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/test/resources/sql/user-service-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 3 | values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); 6 | -------------------------------------------------------------------------------- /Wonchae/test-code-with-architecture/src/test/resources/test-application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1 2 | spring.datasource.driverClassName=org.h2.Driver 3 | spring.datasource.username=sa 4 | spring.datasource.password= 5 | spring.h2.console.enabled=true 6 | 7 | spring.jpa.hibernate.dialect=org.hibernate.dialect.MariaDBDialect 8 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect 9 | spring.jpa.hibernate.ddl-auto=create-drop -------------------------------------------------------------------------------- /Yunbeom/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | 39 | .DS_Store 40 | -------------------------------------------------------------------------------- /Yunbeom/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/Yunbeom/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Yunbeom/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /Yunbeom/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'yunbeom' 2 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/BadRequestException.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom; 2 | 3 | public class BadRequestException extends RuntimeException { 4 | public BadRequestException() { 5 | super("Invalid input request"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/CalculationRequestReader.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom; 2 | 3 | import java.util.Scanner; 4 | 5 | public class CalculationRequestReader { 6 | 7 | public CalculationRequest read() { 8 | System.out.println("Enter two numbers and an operator: "); 9 | Scanner scanner = new Scanner(System.in); 10 | 11 | String result = scanner.nextLine(); 12 | String[] parts = result.split(" "); 13 | return new CalculationRequest(parts); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/Calculator.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom; 2 | 3 | public class Calculator { 4 | 5 | public long calculator(long num1, long num2, String operator) { 6 | // java 12부터 도입된 문법이라 한다. 7 | return switch (operator) { 8 | case "+" -> num1 + num2; 9 | case "-" -> num1 - num2; 10 | case "*" -> num1 * num2; 11 | case "/" -> num1 / num2; 12 | default -> throw new InvalidOperatorException(); 13 | }; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/InvalidOperatorException.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom; 2 | 3 | public class InvalidOperatorException extends RuntimeException{ 4 | public InvalidOperatorException() { 5 | super("Invalid Operator, you need to choose one of +, -, *, /"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/SampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom; 2 | 3 | import java.util.Scanner; 4 | 5 | public class SampleApplication { 6 | 7 | public static void main(String[] args) { 8 | CalculationRequest request = new CalculationRequestReader().read(); 9 | long answer = new Calculator().calculator( 10 | request.getNum1(), 11 | request.getNum2(), 12 | request.getOperator() 13 | ); 14 | System.out.println(answer); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/YunbeomApplication.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class YunbeomApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(YunbeomApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/common/controller/HealthCheckController.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.common.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import io.swagger.v3.oas.annotations.tags.Tag; 8 | 9 | @Tag(name = "헬스 체크") 10 | @RestController 11 | public class HealthCheckController { 12 | 13 | @GetMapping("/health_check.html") 14 | public ResponseEntity healthCheck() { 15 | return ResponseEntity 16 | .ok() 17 | .build(); 18 | } 19 | } -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/common/infrastructure/SystemClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.common.infrastructure; 2 | 3 | import java.time.Clock; 4 | 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.depromeet.yunbeom.common.service.port.ClockHolder; 8 | 9 | @Component 10 | public class SystemClockHolder implements ClockHolder { 11 | @Override 12 | public long millis() { 13 | return Clock.systemUTC().millis(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/common/infrastructure/SystemUuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.common.infrastructure; 2 | 3 | import java.util.UUID; 4 | 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.depromeet.yunbeom.common.service.port.UuidHolder; 8 | 9 | @Component 10 | public class SystemUuidHolder implements UuidHolder { 11 | 12 | @Override 13 | public String random() { 14 | return UUID.randomUUID().toString(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/common/service/port/ClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.common.service.port; 2 | 3 | public interface ClockHolder { 4 | long millis(); 5 | } 6 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/common/service/port/UuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.common.service.port; 2 | 3 | public interface UuidHolder { 4 | String random(); 5 | } 6 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/post/controller/port/PostService.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.post.controller.port; 2 | 3 | import com.depromeet.yunbeom.post.domain.Post; 4 | import com.depromeet.yunbeom.post.domain.PostCreate; 5 | import com.depromeet.yunbeom.post.domain.PostUpdate; 6 | 7 | public interface PostService { 8 | 9 | Post getById(long id); 10 | 11 | Post create(PostCreate postCreate); 12 | 13 | Post update(long id, PostUpdate postUpdate); 14 | } 15 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/post/domain/PostCreate.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class PostCreate { 10 | 11 | private final long writerId; 12 | private final String content; 13 | 14 | @Builder 15 | public PostCreate( 16 | @JsonProperty("writerId") long writerId, 17 | @JsonProperty("content") String content) { 18 | this.writerId = writerId; 19 | this.content = content; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/post/domain/PostUpdate.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class PostUpdate { 10 | 11 | private final String content; 12 | 13 | @Builder 14 | public PostUpdate( 15 | @JsonProperty("content") String content) { 16 | this.content = content; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/post/infrastructure/PostJpaRepository.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.post.infrastructure; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface PostJpaRepository extends JpaRepository { 6 | 7 | } -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/post/infrastructure/PostRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.post.infrastructure; 2 | 3 | import java.util.Optional; 4 | 5 | import org.springframework.stereotype.Repository; 6 | 7 | import com.depromeet.yunbeom.post.domain.Post; 8 | import com.depromeet.yunbeom.post.service.port.PostRepository; 9 | 10 | import lombok.RequiredArgsConstructor; 11 | 12 | @Repository 13 | @RequiredArgsConstructor 14 | public class PostRepositoryImpl implements PostRepository { 15 | 16 | private final PostJpaRepository postJpaRepository; 17 | 18 | @Override 19 | public Optional findById(long id) { 20 | return postJpaRepository.findById(id).map(PostEntity::toModel); 21 | } 22 | 23 | @Override 24 | public Post save(Post post) { 25 | return postJpaRepository.save(PostEntity.from(post)).toModel(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/post/service/port/PostRepository.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.post.service.port; 2 | 3 | import java.util.Optional; 4 | 5 | import com.depromeet.yunbeom.post.domain.Post; 6 | import com.depromeet.yunbeom.post.infrastructure.PostEntity; 7 | 8 | public interface PostRepository { 9 | Optional findById(long id); 10 | 11 | Post save(Post postEntity); 12 | } 13 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/user/controller/port/UserService.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.user.controller.port; 2 | 3 | import com.depromeet.yunbeom.user.domain.User; 4 | import com.depromeet.yunbeom.user.domain.UserCreate; 5 | import com.depromeet.yunbeom.user.domain.UserUpdate; 6 | 7 | public interface UserService { 8 | User getByEmail(String email); 9 | 10 | User getById(long id); 11 | 12 | User create(UserCreate userCreate); 13 | 14 | User update(long id, UserUpdate userUpdate); 15 | 16 | void login(long id); 17 | 18 | void verifyEmail(long id, String certificationCode); 19 | } 20 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/user/controller/request/UserUpdateRequest.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.user.controller.request; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public record UserUpdateRequest(String nickname, String address) { 10 | 11 | @Builder 12 | public UserUpdateRequest( 13 | @JsonProperty("nickname") String nickname, 14 | @JsonProperty("address") String address) { 15 | this.nickname = nickname; 16 | this.address = address; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/user/domain/UserCreate.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class UserCreate { 10 | 11 | private final String email; 12 | private final String nickname; 13 | private final String address; 14 | 15 | @Builder 16 | public UserCreate( 17 | @JsonProperty("email") String email, 18 | @JsonProperty("nickname") String nickname, 19 | @JsonProperty("address") String address) { 20 | this.email = email; 21 | this.nickname = nickname; 22 | this.address = address; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/user/domain/UserStatus.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.user.domain; 2 | 3 | public enum UserStatus { 4 | PENDING, INACTIVE, ACTIVE 5 | } 6 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/user/domain/UserUpdate.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class UserUpdate { 10 | 11 | private final String nickname; 12 | private final String address; 13 | 14 | @Builder 15 | public UserUpdate( 16 | @JsonProperty("nickname") String nickname, 17 | @JsonProperty("address") String address) { 18 | this.nickname = nickname; 19 | this.address = address; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/user/exception/CertificationCodeNotMatchedException.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.user.exception; 2 | 3 | public class CertificationCodeNotMatchedException extends RuntimeException { 4 | 5 | public CertificationCodeNotMatchedException() { 6 | super("자격 증명에 실패하였습니다."); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/user/exception/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.user.exception; 2 | 3 | public class ResourceNotFoundException extends RuntimeException { 4 | 5 | public ResourceNotFoundException(String datasource, long id) { 6 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 7 | } 8 | 9 | public ResourceNotFoundException(String datasource, String id) { 10 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/user/infrastructure/MailSenderImpl.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.user.infrastructure; 2 | 3 | import org.springframework.mail.SimpleMailMessage; 4 | import org.springframework.mail.javamail.JavaMailSender; 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.depromeet.yunbeom.user.service.port.MailSender; 8 | 9 | import lombok.RequiredArgsConstructor; 10 | 11 | @Component 12 | @RequiredArgsConstructor 13 | public class MailSenderImpl implements MailSender { 14 | 15 | private final JavaMailSender mailSender; 16 | 17 | @Override 18 | public void send(String email, String title, String content) { 19 | SimpleMailMessage message = new SimpleMailMessage(); 20 | message.setTo(email); 21 | message.setSubject(title); 22 | message.setText(content); 23 | mailSender.send(message); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/user/infrastructure/UserJpaRepository.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.user.infrastructure; 2 | 3 | import java.util.Optional; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import com.depromeet.yunbeom.user.domain.UserStatus; 8 | 9 | public interface UserJpaRepository extends JpaRepository { 10 | 11 | Optional findByIdAndStatus(long id, UserStatus userStatus); 12 | 13 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 14 | } 15 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/user/service/port/MailSender.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.user.service.port; 2 | 3 | public interface MailSender { 4 | void send(String email, String title, String content); 5 | } 6 | -------------------------------------------------------------------------------- /Yunbeom/src/main/java/com/depromeet/yunbeom/user/service/port/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.user.service.port; 2 | 3 | import java.util.Optional; 4 | 5 | import com.depromeet.yunbeom.user.domain.User; 6 | import com.depromeet.yunbeom.user.domain.UserStatus; 7 | 8 | public interface UserRepository { 9 | 10 | User getById(long id); 11 | 12 | Optional findById(long id); 13 | 14 | Optional findByIdAndStatus(long id, UserStatus userStatus); 15 | 16 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 17 | 18 | User save(User user); 19 | } 20 | -------------------------------------------------------------------------------- /Yunbeom/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | group: 4 | test: "test" 5 | application: 6 | name: yunbeom 7 | h2: 8 | console: 9 | enabled: true 10 | path: /h2-console 11 | datasource: 12 | url: jdbc:h2:~/mem-data; 13 | driverClassName: org.h2.Driver 14 | username: sa 15 | password: 16 | jpa: 17 | hibernate: 18 | ddl-auto: create 19 | database-platform: org.hibernate.dialect.H2Dialect 20 | doc: 21 | swagger-ui: 22 | path: /swagger-ui.html 23 | mail: 24 | host: smtp.gmail.com 25 | port: 587 26 | username: ${MAIL_USERNAME} 27 | password: ${MAIL_APPLICATION_PASSWORD} 28 | properties: 29 | mail: 30 | smtp: 31 | auth: true 32 | timeout: 5000 33 | starttls: 34 | enable: true 35 | -------------------------------------------------------------------------------- /Yunbeom/src/test/java/com/depromeet/yunbeom/CalculationRequestReaderTest.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom; 2 | 3 | import static org.assertj.core.api.AssertionsForClassTypes.*; 4 | 5 | import java.io.ByteArrayInputStream; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | class CalculationRequestReaderTest { 10 | 11 | @Test 12 | public void System_in_데이터를_읽는다() { 13 | // given 14 | CalculationRequestReader calculationRequestReader = new CalculationRequestReader(); 15 | 16 | // when 17 | System.setIn(new ByteArrayInputStream("1 + 2".getBytes())); 18 | CalculationRequest result = calculationRequestReader.read(); 19 | 20 | // then 21 | assertThat(result.getNum1()).isEqualTo(1); 22 | assertThat(result.getNum2()).isEqualTo(2); 23 | assertThat(result.getOperator()).isEqualTo("+"); 24 | } 25 | } -------------------------------------------------------------------------------- /Yunbeom/src/test/java/com/depromeet/yunbeom/YunbeomApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | import org.springframework.context.annotation.Import; 6 | import org.springframework.test.context.ActiveProfiles; 7 | import org.springframework.test.context.TestPropertySource; 8 | 9 | @SpringBootTest 10 | @TestPropertySource("classpath:application-test.yml") 11 | class YunbeomApplicationTests { 12 | 13 | @Test 14 | void contextLoads() { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Yunbeom/src/test/java/com/depromeet/yunbeom/mock/FakeMailSender.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.mock; 2 | 3 | import com.depromeet.yunbeom.user.service.port.MailSender; 4 | 5 | public class FakeMailSender implements MailSender { 6 | 7 | // 실제 값 확인 용도 8 | public String email; 9 | public String title; 10 | public String content; 11 | 12 | @Override 13 | public void send(String email, String title, String content) { 14 | this.email = email; 15 | this.title = title; 16 | this.content = content; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Yunbeom/src/test/java/com/depromeet/yunbeom/mock/TestClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.mock; 2 | 3 | import com.depromeet.yunbeom.common.service.port.ClockHolder; 4 | 5 | import lombok.RequiredArgsConstructor; 6 | 7 | @RequiredArgsConstructor 8 | public class TestClockHolder implements ClockHolder { 9 | 10 | private final long millis; 11 | @Override 12 | public long millis() { 13 | return millis; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Yunbeom/src/test/java/com/depromeet/yunbeom/mock/TestUuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.depromeet.yunbeom.mock; 2 | 3 | import com.depromeet.yunbeom.common.service.port.UuidHolder; 4 | 5 | import lombok.RequiredArgsConstructor; 6 | 7 | @RequiredArgsConstructor 8 | public class TestUuidHolder implements UuidHolder { 9 | 10 | private final String uuid; 11 | 12 | @Override 13 | public String random() { 14 | return uuid; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Yunbeom/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | config: 3 | activate: 4 | on-profile: "test" 5 | datasource: 6 | url: jdbc:h2:mem:test 7 | driverClassName: org.h2.Driver 8 | username: sa 9 | password: 10 | h2: 11 | console: 12 | enabled: true 13 | path: /h2-console 14 | jpa: 15 | hibernate: 16 | ddl-auto: create-drop 17 | database-platform: org.hibernate.dialect.H2Dialect 18 | show-sql: true 19 | -------------------------------------------------------------------------------- /Yunbeom/src/test/resources/sql/delete-all-data.sql: -------------------------------------------------------------------------------- 1 | delete from `posts` where 1; 2 | delete from `users` where 1; -------------------------------------------------------------------------------- /Yunbeom/src/test/resources/sql/post-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 3 | values (1, 'uiurihappy@naver.com', 'uiurihappy', 'Seoul', '1234asda-1321dada-12dascasc', 'ACTIVE', 0); 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (2, 'ybchar@naver.com', 'ybchar', 'Seoul', '1234asda-1321dada-12dascascet', 'PENDING', 0); 6 | insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) 7 | values (11, 'helloworld', 1678530673958, 0, 1); -------------------------------------------------------------------------------- /Yunbeom/src/test/resources/sql/post-service-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 3 | values (1, 'uiurihappy@naver.com', 'uiurihappy', 'Seoul', '1234asda-1321dada-12dascasc', 'ACTIVE', 0); 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (2, 'ybchar@naver.com', 'ybchar', 'Seoul', '1234asda-1321dada-12dascascet', 'PENDING', 0); 6 | insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`) 7 | values (11, 'helloworld', 1678530673958, 0, 1); -------------------------------------------------------------------------------- /Yunbeom/src/test/resources/sql/user-controller-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 3 | values (11, 'uiurihappy@naver.com', 'uiurihappy', 'Seoul', '1234asda-1321dada-12dascasc', 'ACTIVE', 0); 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (12, 'ybchar@naver.com', 'ybchar', 'Seoul', '1234asda-1321dada-12dascascet', 'PENDING', 0); -------------------------------------------------------------------------------- /Yunbeom/src/test/resources/sql/user-repository-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 3 | values (1, 'uiurihappy@naver.com', 'uiurihappy', 'Seoul', '1234asda-1321dada-12dascasc', 'ACTIVE', 0); -------------------------------------------------------------------------------- /Yunbeom/src/test/resources/sql/user-service-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 3 | values (11, 'uiurihappy@naver.com', 'uiurihappy', 'Seoul', '1234asda-1321dada-12dascasc', 'ACTIVE', 0); 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (12, 'ybchar@naver.com', 'ybchar', 'Seoul', '1234asda-1321dada-12dascascet', 'PENDING', 0); -------------------------------------------------------------------------------- /domo/calculator/build.gradle: -------------------------------------------------------------------------------- 1 | package calculator 2 | 3 | plugins { 4 | id 'java' 5 | } 6 | 7 | group = 'com.dev-domo' 8 | version = '1.0-SNAPSHOT' 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | testImplementation platform('org.junit:junit-bom:5.9.1') 16 | testImplementation 'org.junit.jupiter:junit-jupiter' 17 | } 18 | 19 | test { 20 | useJUnitPlatform() 21 | } -------------------------------------------------------------------------------- /domo/calculator/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/domo/calculator/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /domo/calculator/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Jun 15 00:07:51 KST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /domo/calculator/settings.gradle: -------------------------------------------------------------------------------- 1 | package calculator 2 | 3 | rootProject.name = 'domo' 4 | 5 | -------------------------------------------------------------------------------- /domo/calculator/src/main/java/BadRequestException.java: -------------------------------------------------------------------------------- 1 | package calculator.src.main.java; 2 | 3 | public class BadRequestException extends RuntimeException { 4 | public BadRequestException() { 5 | super("Invalid input size, you must input 3 length"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /domo/calculator/src/main/java/CalculationRequestReader.java: -------------------------------------------------------------------------------- 1 | package calculator.src.main.java; 2 | 3 | import java.util.Scanner; 4 | 5 | public class CalculationRequestReader { 6 | public CalculationRequest read() { 7 | Scanner sc = new Scanner(System.in); 8 | System.out.println("Enter two numbers and an operator (eg. 1 + 2): "); 9 | String[] parts = sc.nextLine().split(" "); 10 | return new CalculationRequest(parts); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /domo/calculator/src/main/java/Calculator.java: -------------------------------------------------------------------------------- 1 | package calculator.src.main.java; 2 | 3 | public class Calculator { 4 | public long calculate(long num1, long num2, String operator) { 5 | return switch (operator) { 6 | case "+" -> num1 + num2; 7 | case "-" -> num1 - num2; 8 | case "*" -> num1 * num2; 9 | case "/" -> num1 / num2; 10 | default -> throw new InvalidOperatorException(); 11 | }; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /domo/calculator/src/main/java/InvalidOperatorException.java: -------------------------------------------------------------------------------- 1 | package calculator.src.main.java; 2 | 3 | public class InvalidOperatorException extends RuntimeException { 4 | public InvalidOperatorException() { 5 | super("Invalid operator, you need to choose one of (+, -, *, /)"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /domo/calculator/src/main/java/Main.java: -------------------------------------------------------------------------------- 1 | package calculator.src.main.java; 2 | 3 | import java.util.Scanner; 4 | 5 | public class Main { 6 | public static void main(String[] args) { 7 | CalculationRequest request = new CalculationRequestReader().read(); 8 | long answer = new Calculator().calculate( 9 | request.getNum1(), 10 | request.getNum2(), 11 | request.getOperator() 12 | ); 13 | System.out.println(answer); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /domo/toy/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | -------------------------------------------------------------------------------- /domo/toy/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depromeet/15th-Spring-Test-Study/13971064f6e5e0c78a3a3fd89473d79e18abed23/domo/toy/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /domo/toy/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /domo/toy/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'toy' 2 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/ToyApplication.java: -------------------------------------------------------------------------------- 1 | package com.domo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ToyApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(ToyApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/common/controller/HealthCheckController.java: -------------------------------------------------------------------------------- 1 | package com.domo.common.controller; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import io.swagger.v3.oas.annotations.tags.Tag; 8 | 9 | @Tag(name = "헬스 체크") 10 | @RestController 11 | public class HealthCheckController { 12 | 13 | @GetMapping("/health_check.html") 14 | public ResponseEntity healthCheck() { 15 | return ResponseEntity 16 | .ok() 17 | .build(); 18 | } 19 | } -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/common/domain/exception/CertificationCodeNotMatchedException.java: -------------------------------------------------------------------------------- 1 | package com.domo.common.domain.exception; 2 | 3 | public class CertificationCodeNotMatchedException extends RuntimeException { 4 | 5 | public CertificationCodeNotMatchedException() { 6 | super("자격 증명에 실패하였습니다."); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/common/domain/exception/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.domo.common.domain.exception; 2 | 3 | public class ResourceNotFoundException extends RuntimeException { 4 | 5 | public ResourceNotFoundException(String datasource, long id) { 6 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 7 | } 8 | 9 | public ResourceNotFoundException(String datasource, String id) { 10 | super(datasource + "에서 ID " + id + "를 찾을 수 없습니다."); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/common/infrastructure/SystemClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.domo.common.infrastructure; 2 | 3 | import com.domo.common.service.port.ClockHolder; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.time.Clock; 7 | 8 | @Component 9 | public class SystemClockHolder implements ClockHolder { 10 | @Override 11 | public long millis() { 12 | return Clock.systemUTC().millis(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/common/infrastructure/SystemUuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.domo.common.infrastructure; 2 | 3 | import com.domo.common.service.port.UuidHolder; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.UUID; 7 | 8 | @Component 9 | public class SystemUuidHolder implements UuidHolder { 10 | @Override 11 | public String random() { 12 | return UUID.randomUUID().toString(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/common/service/port/ClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.domo.common.service.port; 2 | 3 | public interface ClockHolder { 4 | long millis(); 5 | } 6 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/common/service/port/UuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.domo.common.service.port; 2 | 3 | public interface UuidHolder { 4 | String random(); 5 | } 6 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/post/controller/port/PostService.java: -------------------------------------------------------------------------------- 1 | package com.domo.post.controller.port; 2 | 3 | import com.domo.post.domain.Post; 4 | import com.domo.post.domain.PostCreate; 5 | import com.domo.post.domain.PostUpdate; 6 | 7 | public interface PostService { 8 | Post getPostById(long id); 9 | Post create(PostCreate postCreate); 10 | Post update(long id, PostUpdate postUpdate); 11 | } 12 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/post/domain/PostCreate.java: -------------------------------------------------------------------------------- 1 | package com.domo.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class PostCreate { 10 | 11 | private final long writerId; 12 | private final String content; 13 | 14 | @Builder 15 | public PostCreate( 16 | @JsonProperty("writerId") long writerId, 17 | @JsonProperty("content") String content) { 18 | this.writerId = writerId; 19 | this.content = content; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/post/domain/PostUpdate.java: -------------------------------------------------------------------------------- 1 | package com.domo.post.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class PostUpdate { 10 | 11 | private final String content; 12 | 13 | @Builder 14 | public PostUpdate( 15 | @JsonProperty("content") String content) { 16 | this.content = content; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/post/infstructure/PostJpaRepository.java: -------------------------------------------------------------------------------- 1 | package com.domo.post.infstructure; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface PostJpaRepository extends JpaRepository { 6 | 7 | } -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/post/infstructure/PostRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.domo.post.infstructure; 2 | 3 | import com.domo.post.domain.Post; 4 | import com.domo.post.service.port.PostRepository; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.Optional; 9 | 10 | @Repository 11 | @RequiredArgsConstructor 12 | public class PostRepositoryImpl implements PostRepository { 13 | private final PostJpaRepository postJpaRepository; 14 | 15 | @Override 16 | public Optional findById(long id) { 17 | return postJpaRepository.findById(id).map(PostEntity::toDomain); 18 | } 19 | 20 | @Override 21 | public Post save(Post post) { 22 | return postJpaRepository.save(PostEntity.fromDomain(post)).toDomain(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/post/service/port/PostRepository.java: -------------------------------------------------------------------------------- 1 | package com.domo.post.service.port; 2 | 3 | import com.domo.post.domain.Post; 4 | import com.domo.post.infstructure.PostEntity; 5 | 6 | import java.util.Optional; 7 | 8 | public interface PostRepository { 9 | Optional findById(long id); 10 | 11 | Post save(Post postEntity); 12 | } 13 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/user/controller/port/UserService.java: -------------------------------------------------------------------------------- 1 | package com.domo.user.controller.port; 2 | 3 | import com.domo.user.domain.User; 4 | import com.domo.user.domain.UserCreate; 5 | import com.domo.user.domain.UserUpdate; 6 | 7 | public interface UserService { 8 | User getByEmail(String email); 9 | User getById(long id); 10 | User create(UserCreate userCreate); 11 | User update(long id, UserUpdate userUpdate); 12 | void login(long id); 13 | void verifyEmail(long id, String certificationCode); 14 | } 15 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/user/domain/UserCreate.java: -------------------------------------------------------------------------------- 1 | package com.domo.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class UserCreate { 10 | 11 | private final String email; 12 | private final String nickname; 13 | private final String address; 14 | 15 | @Builder 16 | public UserCreate( 17 | @JsonProperty("email") String email, 18 | @JsonProperty("nickname") String nickname, 19 | @JsonProperty("address") String address) { 20 | this.email = email; 21 | this.nickname = nickname; 22 | this.address = address; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/user/domain/UserStatus.java: -------------------------------------------------------------------------------- 1 | package com.domo.user.domain; 2 | 3 | public enum UserStatus { 4 | PENDING, INACTIVE, ACTIVE 5 | } 6 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/user/domain/UserUpdate.java: -------------------------------------------------------------------------------- 1 | package com.domo.user.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import lombok.Builder; 6 | import lombok.Getter; 7 | 8 | @Getter 9 | public class UserUpdate { 10 | 11 | private final String nickname; 12 | private final String address; 13 | 14 | @Builder 15 | public UserUpdate( 16 | @JsonProperty("nickname") String nickname, 17 | @JsonProperty("address") String address) { 18 | this.nickname = nickname; 19 | this.address = address; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/user/infstructure/MailSenderImpl.java: -------------------------------------------------------------------------------- 1 | package com.domo.user.infstructure; 2 | 3 | import com.domo.user.service.port.MailSender; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.mail.SimpleMailMessage; 6 | import org.springframework.mail.javamail.JavaMailSender; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | @RequiredArgsConstructor 11 | public class MailSenderImpl implements MailSender { 12 | private final JavaMailSender javaMailSender; 13 | 14 | @Override 15 | public void send(String email, String title, String content) { 16 | SimpleMailMessage message = new SimpleMailMessage(); 17 | message.setTo(email); 18 | message.setSubject(title); 19 | message.setText(content); 20 | javaMailSender.send(message); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/user/infstructure/UserJpaRepository.java: -------------------------------------------------------------------------------- 1 | package com.domo.user.infstructure; 2 | 3 | import com.domo.user.domain.UserStatus; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.Optional; 7 | 8 | 9 | public interface UserJpaRepository extends JpaRepository { 10 | Optional findByIdAndStatus(long id, UserStatus userStatus); 11 | 12 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 13 | } 14 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/user/service/port/MailSender.java: -------------------------------------------------------------------------------- 1 | package com.domo.user.service.port; 2 | 3 | public interface MailSender { 4 | void send(String email, String title, String content); 5 | } 6 | -------------------------------------------------------------------------------- /domo/toy/src/main/java/com/domo/user/service/port/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.domo.user.service.port; 2 | 3 | import com.domo.user.domain.User; 4 | import com.domo.user.domain.UserStatus; 5 | import com.domo.user.infstructure.UserEntity; 6 | 7 | import java.util.Optional; 8 | 9 | public interface UserRepository { 10 | Optional findById(long id); 11 | Optional findByIdAndStatus(long id, UserStatus userStatus); 12 | 13 | Optional findByEmailAndStatus(String email, UserStatus userStatus); 14 | 15 | User save(User user); 16 | 17 | User getById(long id); 18 | } 19 | -------------------------------------------------------------------------------- /domo/toy/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | h2: 3 | console: 4 | enabled: true 5 | path: /h2-console 6 | datasource: 7 | url: jdbc:h2:~/mem-data 8 | driverClassName: org.h2.Driver 9 | username: sa 10 | password: 11 | jpa: 12 | hibernate: 13 | ddl-auto: create 14 | database-platform: org.hibernate.dialect.H2Dialect 15 | doc: 16 | swagger-ui: 17 | path: /swagger-ui.html 18 | mail: 19 | host: smtp.gmail.com 20 | port: 587 21 | username: ${MAIL_USERNAME} 22 | password: ${MAIL_APPLICATION_PASSWORD} 23 | properties: 24 | mail: 25 | smtp: 26 | auth: true 27 | timeout: 5000 28 | starttls: 29 | enable: true 30 | -------------------------------------------------------------------------------- /domo/toy/src/test/java/com/domo/ToyApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.domo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class ToyApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /domo/toy/src/test/java/com/domo/mock/FakeMailSender.java: -------------------------------------------------------------------------------- 1 | package com.domo.mock; 2 | 3 | import com.domo.user.service.port.MailSender; 4 | 5 | public class FakeMailSender implements MailSender { 6 | public String email; 7 | public String title; 8 | public String content; 9 | 10 | @Override 11 | public void send(String email, String title, String content) { 12 | this.email = email; 13 | this.title = title; 14 | this.content = content; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /domo/toy/src/test/java/com/domo/mock/TestClockHolder.java: -------------------------------------------------------------------------------- 1 | package com.domo.mock; 2 | 3 | import com.domo.common.service.port.ClockHolder; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @RequiredArgsConstructor 7 | public class TestClockHolder implements ClockHolder { 8 | private final long millis; 9 | 10 | @Override 11 | public long millis() { 12 | return millis; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /domo/toy/src/test/java/com/domo/mock/TestUuidHolder.java: -------------------------------------------------------------------------------- 1 | package com.domo.mock; 2 | 3 | import com.domo.common.service.port.UuidHolder; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @RequiredArgsConstructor 7 | public class TestUuidHolder implements UuidHolder { 8 | private final String uuid; 9 | 10 | @Override 11 | public String random() { 12 | return uuid; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /domo/toy/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | h2: 3 | console: 4 | enabled: true 5 | path: /h2-console 6 | datasource: 7 | url: jdbc:h2:~/mem-data 8 | driverClassName: org.h2.Driver 9 | username: sa 10 | password: 11 | jpa: 12 | hibernate: 13 | ddl-auto: create-drop 14 | database-platform: org.hibernate.dialect.H2Dialect 15 | doc: 16 | swagger-ui: 17 | path: /swagger-ui.html 18 | mail: 19 | host: smtp.gmail.com 20 | port: 587 21 | username: ${MAIL_USERNAME} 22 | password: ${MAIL_APPLICATION_PASSWORD} 23 | properties: 24 | mail: 25 | smtp: 26 | auth: true 27 | timeout: 5000 28 | starttls: 29 | enable: true 30 | -------------------------------------------------------------------------------- /domo/toy/src/test/resources/sql/delete-all-data.sql: -------------------------------------------------------------------------------- 1 | delete from `posts` where 1; 2 | delete from `users` where 1; -------------------------------------------------------------------------------- /domo/toy/src/test/resources/sql/post-service-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'me@dev-domo.com', 'domo', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (2, 'me@dev-domo1.com', 'domo1', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); 6 | 7 | insert into `posts` (`id`, `content`, `created_at`, `updated_at`, `user_id`) 8 | values (16, 'Hello, world!', 1678530673958, 0, 1); -------------------------------------------------------------------------------- /domo/toy/src/test/resources/sql/user-repository-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'me@dev-domo.com', 'domo', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); -------------------------------------------------------------------------------- /domo/toy/src/test/resources/sql/user-service-test-data.sql: -------------------------------------------------------------------------------- 1 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 2 | values (1, 'me@dev-domo.com', 'domo', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0); 3 | 4 | insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`) 5 | values (2, 'me@dev-domo1.com', 'domo1', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0); --------------------------------------------------------------------------------