Skip to content

Commit

Permalink
feature/#98 User 단위 및 통합 테스트코드 구현 (#101)
Browse files Browse the repository at this point in the history
* refactor: User 코드 포맷팅

* refactor: Dept 코드로 축약

* feat: UserDomainTest 테스트 코드 구현

* refactor: coderabbit yaml 삭제

* feat: 통합 테스트를 위한 testFixtures 적용

* feat: UserServiceTest 구현

* feat: AuthServiceTest 구현

* feat: AuthControllerTest 구현

* feat: 중형 테스트 설명

* feat: AtomicLong 사용 예시

* Update aics-common/src/main/java/kgu/developers/common/auth/jwt/JwtProperties.java

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix: JwtProperties 컴파일 에러 해결

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
  • Loading branch information
LeeHanEum and coderabbitai[bot] authored Nov 16, 2024
1 parent 5634485 commit 7bea2da
Show file tree
Hide file tree
Showing 25 changed files with 526 additions and 52 deletions.
14 changes: 0 additions & 14 deletions .coderabbit.yaml

This file was deleted.

10 changes: 9 additions & 1 deletion aics-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@ bootJar {
}

jar {
enabled = false
enabled = true
}

dependencies {
implementation project(':aics-domain')
implementation project(':aics-common')
implementation project(':aics-infra')
implementation project(':aics-global-utils')

testFixturesImplementation project(':aics-domain')
testFixturesImplementation project(':aics-common')
testFixturesImplementation project(':aics-infra')
testFixturesImplementation project(':aics-global-utils')

testFixturesImplementation testFixtures(project(':aics-domain'))
testFixturesImplementation testFixtures(project(':aics-global-utils'))
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
import kgu.developers.api.user.application.UserService;
import kgu.developers.common.auth.jwt.TokenProvider;
import kgu.developers.domain.user.domain.User;
import lombok.Builder;
import lombok.RequiredArgsConstructor;

@Service
@Builder
@RequiredArgsConstructor
public class AuthService {
private final UserService userService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
import kgu.developers.api.auth.application.AuthService;
import kgu.developers.api.auth.presentation.request.LoginRequest;
import kgu.developers.api.auth.presentation.response.TokenResponse;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Builder
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/auth")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;

@Builder
public record LoginRequest(
@Schema(description = "학번", example = "202412345", requiredMode = REQUIRED)
@NotNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
import kgu.developers.domain.user.domain.User;
import kgu.developers.domain.user.domain.UserRepository;
import kgu.developers.domain.user.exception.UserNotFoundException;
import lombok.Builder;
import lombok.RequiredArgsConstructor;

@Service
@Builder
@RequiredArgsConstructor
public class UserService {
private final BCryptPasswordEncoder bCryptPasswordEncoder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import kgu.developers.domain.user.domain.Major;
import lombok.Builder;

@Builder
public record UserCreateRequest(

@Schema(description = "학번", example = "202412345", requiredMode = REQUIRED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Pattern;
import lombok.Builder;

@Builder
public record UserUpdateRequest(
@Schema(description = "전화번호", example = "010-1234-5678", requiredMode = REQUIRED)
@Pattern(regexp = "^\\d{2,4}-\\d{3,4}-\\d{4}$", message = "유효한 전화번호 형식이 아닙니다.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package auth.application;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import kgu.developers.api.auth.application.AuthService;
import kgu.developers.api.auth.presentation.exception.InvalidPasswordException;
import kgu.developers.api.auth.presentation.request.LoginRequest;
import kgu.developers.api.user.application.UserService;
import kgu.developers.common.auth.jwt.JwtProperties;
import kgu.developers.common.auth.jwt.TokenProvider;
import kgu.developers.domain.user.domain.Major;
import kgu.developers.domain.user.domain.User;
import mock.FakeUserRepository;

public class AuthServiceTest {
private AuthService authService;

@BeforeEach
public void init() {
FakeUserRepository fakeUserRepository = new FakeUserRepository();
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();

this.authService = AuthService.builder()
.userService(
UserService.builder()
.userRepository(fakeUserRepository)
.bCryptPasswordEncoder(bCryptPasswordEncoder)
.build()
)
.passwordEncoder(bCryptPasswordEncoder)
.tokenProvider(
TokenProvider.builder()
.jwtProperties(new JwtProperties("testIssuer", "testSecretKey"))
.build()
)
.build();

fakeUserRepository.save(User.builder()
.id("202411345")
.password(bCryptPasswordEncoder.encode("password1234"))
.name("홍길동")
.email("test@kyonggi.ac.kr")
.phone("010-1234-5678")
.major(Major.CSE)
.build());
}

@Test
@DisplayName("login은 토큰을 발급할 수 있다")
public void login_Success() {
// given
String userId = "202411345";
String password = "password1234";

// when
// then
assertThatCode(() -> {
authService.login(LoginRequest.builder()
.userId(userId)
.password(password)
.build()
);
}).doesNotThrowAnyException();
}

@Test
@DisplayName("login은 비밀번호가 틀리면 InvalidPasswordException을 발생시킨다")
public void login_InvalidPassword_ThrowsException() {
// given
String userId = "202411345";
String password = "wrongPassword";

// when
// then
assertThatThrownBy(() -> {
authService.login(LoginRequest.builder()
.userId(userId)
.password(password)
.build()
);
}).isInstanceOf(InvalidPasswordException.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package auth.presentation;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Objects;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;

import kgu.developers.api.auth.presentation.request.LoginRequest;
import kgu.developers.api.auth.presentation.response.TokenResponse;
import kgu.developers.api.user.presentation.request.UserCreateRequest;
import kgu.developers.domain.user.domain.Major;
import mock.TestContainer;
/*
* 추후 Controller 테스트는 medium test로 전환할 예정입니다.
* medium test는 Controller / Service / Repository 계층을 함께 테스트합니다.
*/
public class AuthControllerTest {

@Test
@DisplayName("로그인 성공 후 200 상태 코드와 토큰을 정상적으로 발급받는다")
public void login_Success() {
// given
TestContainer testContainer = new TestContainer();
testContainer.userService.createUser(UserCreateRequest.builder()
.userId("202411345")
.password("password0000")
.name("김철수")
.email("kim@kyonggi.ac.kr")
.phone("010-0000-0000")
.major(Major.CSE)
.build());

// when
ResponseEntity<TokenResponse> result = testContainer.authController.login(LoginRequest.builder()
.userId("202411345")
.password("password0000")
.build());

// then
assertThat(result.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(200));
assertThat(Objects.requireNonNull(result.getBody()).accessToken()).isNotNull();
assertThat(Objects.requireNonNull(result.getBody()).refreshToken()).isNotNull();
}
}
37 changes: 37 additions & 0 deletions aics-api/src/testFixtures/java/mock/TestContainer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package mock;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import kgu.developers.api.auth.application.AuthService;
import kgu.developers.api.auth.presentation.AuthController;
import kgu.developers.api.user.application.UserService;
import kgu.developers.common.auth.jwt.JwtProperties;
import kgu.developers.common.auth.jwt.TokenProvider;
import kgu.developers.domain.user.domain.UserRepository;

public class TestContainer {
public final UserRepository userRepository;
public final UserService userService;
public final AuthService authService;
public final AuthController authController;

public TestContainer() {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
this.userRepository = new FakeUserRepository();
this.userService = UserService.builder()
.userRepository(this.userRepository)
.bCryptPasswordEncoder(bCryptPasswordEncoder)
.build();
this.authService = AuthService.builder()
.userService(this.userService)
.passwordEncoder(bCryptPasswordEncoder)
.tokenProvider(TokenProvider.builder()
.jwtProperties(new JwtProperties("testIssuer", "testSecretKey"))
.build()
)
.build();
this.authController = AuthController.builder()
.authService(this.authService)
.build();
}
}
Loading

0 comments on commit 7bea2da

Please sign in to comment.