Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release: User 제외 모든 도메인 테스트 적용 #32

Merged
merged 31 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
54b92b5
test: auth - domain, infrastructure layer 테스팅
EunChanNam Oct 21, 2023
088e058
test: auth - application layer 테스트
EunChanNam Oct 21, 2023
d64059a
test: global - 인증관련 인터셉터 테스트
EunChanNam Oct 24, 2023
aa808a5
test: Auth Api 테스트
EunChanNam Oct 27, 2023
67cfec5
feat: 좋아요 관련 리뷰 쿼리 모두 join 제거하고 Review 테이블에 likeCount를 추가한다. 동시성에 대한 …
EunChanNam Oct 31, 2023
b303b90
feat: 좋아요 기능에 레디스 적용해서 동시성 + 성능 문제 해결
EunChanNam Nov 3, 2023
eb40aa0
enhancement: 외래키 제약조건 모두 제거
EunChanNam Nov 3, 2023
a80fa6c
test: pointlog 도메인 계층 테스트
EunChanNam Nov 3, 2023
ddf0d7f
test: pointLog 애플리케이션 계층 테스트
EunChanNam Nov 3, 2023
f524abc
test: pointLog API 테스트
EunChanNam Nov 4, 2023
8012fe3
test: photo 도메인 게층 테스트
EunChanNam Nov 4, 2023
41c1b6f
test: photo Application 게층 테스트
EunChanNam Nov 4, 2023
37f2a9c
Revert "test: photo Application 게층 테스트"
EunChanNam Nov 4, 2023
d289894
Revert "test: photo 도메인 게층 테스트"
EunChanNam Nov 4, 2023
68f9719
test: photo 도메인 게층 테스트
EunChanNam Nov 4, 2023
7f61755
test: photo Application 게층 테스트
EunChanNam Nov 4, 2023
ac49942
chore: 임베디드 레디스(테스트용) 의존성 추가
EunChanNam Nov 4, 2023
988b26a
chore: 임베디드 레디스 버전 변경
EunChanNam Nov 4, 2023
bc70026
test: 포인트 조회 API 테스트
EunChanNam Nov 4, 2023
f6291c0
test: hairstyle Domain 계층 테스트
EunChanNam Nov 5, 2023
3ddb96f
refactor: 찜 관련 코드 리팩토링
EunChanNam Nov 11, 2023
d3ba9b5
feat: Redis 테스트 설정 추가
EunChanNam Nov 11, 2023
32927bf
feat: HairStyle Application 계층 테스트
EunChanNam Nov 11, 2023
7a2a9a5
refactor: API 테스트 통합테스트로 돌아가도록 변경
EunChanNam Nov 11, 2023
64e81f8
test: HairStyle API 테스트
EunChanNam Nov 11, 2023
124489b
test: Review 도메인 계층 테스트
EunChanNam Nov 12, 2023
e2001db
test: RedisUtils 테스트
EunChanNam Nov 13, 2023
33ec3dc
test: Review Application 계층 테스트
EunChanNam Nov 14, 2023
3db47b7
test: Review ScoreConverter 테스트
EunChanNam Nov 14, 2023
1b17d04
test: Review API 테스트
EunChanNam Nov 14, 2023
c437673
resolve: 충돌 해결
EunChanNam Nov 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ dependencies {
runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'com.h2database:h2'

//Redis
implementation('it.ozimov:embedded-redis:0.7.2')
implementation 'org.springframework.boot:spring-boot-starter-data-redis'

//네이버 클라우드
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

Expand Down Expand Up @@ -119,7 +123,8 @@ jacocoTestReport {
'**/*Application*',
"**/config/**",
"**/exception/**",
"**/dto/**"
"**/dto/**",
"**/Q*/**"
])
})
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ public class TokenReissueController {

private final TokenReissueService tokenReissueService;

@PostMapping("/token/reissue")
public ResponseEntity<TokenResponse> reissueToken(
final @FetchAuthInfo AuthInfo authInfo
) {
@PostMapping("/tokens/reissue")
public ResponseEntity<TokenResponse> reissueToken(@FetchAuthInfo AuthInfo authInfo) {
TokenResponse response = tokenReissueService.reissueToken(authInfo.userId(), authInfo.token());
return ResponseEntity.ok(response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
Expand All @@ -16,18 +15,9 @@
@Getter
public class BaseEntity {

@Column(
nullable = false,
insertable = false,
updatable = false,
columnDefinition = "datetime default CURRENT_TIMESTAMP")
@CreatedDate
protected LocalDateTime createdDate;

@Column(
nullable = false,
insertable = false,
columnDefinition = "datetime default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP")
@LastModifiedDate
private LocalDateTime updatedDate;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.inq.wishhair.wesharewishhair.global.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

@Value("${spring.data.redis.host}")
public String host;
@Value("${spring.data.redis.port}")
public int port;

@Bean
public LettuceConnectionFactory lettuceConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}

@Bean
public RedisTemplate<String, Long> cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Long> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericToStringSerializer<>(Long.class));
return redisTemplate;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.inq.wishhair.wesharewishhair.global.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
public class SchedulerConfig {
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import com.inq.wishhair.wesharewishhair.review.presentation.ReviewController;
import com.inq.wishhair.wesharewishhair.review.presentation.ReviewSearchController;
import com.inq.wishhair.wesharewishhair.point.presentation.PointController;
import com.inq.wishhair.wesharewishhair.point.presentation.PointSearchController;
import com.inq.wishhair.wesharewishhair.user.presentation.UserController;
import com.inq.wishhair.wesharewishhair.user.presentation.UserInfoController;

Expand All @@ -26,7 +25,7 @@
ReviewController.class, WishHairController.class, AuthController.class,
TokenReissueController.class, MailAuthController.class,
UserInfoController.class, LikeReviewController.class, ReviewSearchController.class,
PointSearchController.class, PointController.class
PointController.class
})
public class ApiExceptionHandler {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ public enum ErrorCode {
FLASK_SERVER_EXCEPTION("FLASK_001", "Flask 서버 요청 간 에러가 발생하였습니다.", HttpStatus.INTERNAL_SERVER_ERROR),
FLASK_RESPONSE_ERROR("FLASK_002", "Flask 서버의 응답값의 형식이 올바르지 않습니다.", HttpStatus.INTERNAL_SERVER_ERROR),

AOP_GENERIC_EXCEPTION("AOP_001", "AOP 에서 발생한 Generic 에러 입니다.", HttpStatus.INTERNAL_SERVER_ERROR);
AOP_GENERIC_EXCEPTION("AOP_001", "AOP 에서 발생한 Generic 에러 입니다.", HttpStatus.INTERNAL_SERVER_ERROR),

REDIS_FAIL_ACQUIRE_LOCK("REDIS_001", "서버 일시적 오류입니다. 재시도 해주세요", HttpStatus.INTERNAL_SERVER_ERROR);

private final String code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ public static Pageable generateSimplePageable(int size) {
public static Pageable generateDateDescPageable(int size) {
return PageRequest.of(0, size, Sort.by(Sort.Direction.DESC, DATE));
}

public static Pageable generateDateAscPageable(int size) {
return PageRequest.of(0, size, Sort.by(Sort.Direction.ASC, DATE));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.inq.wishhair.wesharewishhair.global.utils;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class RedisUtils {

private final RedisTemplate<String, Long> redisTemplate;
private final long expireTime;

public RedisUtils(
RedisTemplate<String, Long> redisTemplate,
@Value("${spring.data.redis.expire-time}") long expireTime
) {
this.redisTemplate = redisTemplate;
this.expireTime = expireTime;
}

public void setData(Long key, Long value) {
redisTemplate
.opsForValue()
.set(String.valueOf(key), value, expireTime, TimeUnit.MILLISECONDS);
}

public void increaseData(Long key) {
redisTemplate.opsForValue().increment(String.valueOf(key));
}

public void decreaseData(Long key) {
redisTemplate.opsForValue().decrement(String.valueOf(key));
}

public Optional<Long> getData(Long key) {
return Optional.ofNullable(
redisTemplate.opsForValue().get(String.valueOf(key))
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class HairStyleFindService {

private final HairStyleRepository hairStyleRepository;

public HairStyle findById(Long id) {
public HairStyle getById(Long id) {
return hairStyleRepository.findById(id)
.orElseThrow(() -> new WishHairException(ErrorCode.NOT_EXIST_KEY));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,21 @@
import com.inq.wishhair.wesharewishhair.global.dto.response.ResponseWrapper;
import com.inq.wishhair.wesharewishhair.global.exception.ErrorCode;
import com.inq.wishhair.wesharewishhair.global.exception.WishHairException;
import com.inq.wishhair.wesharewishhair.hairstyle.application.query.HairStyleQueryRepository;
import com.inq.wishhair.wesharewishhair.hairstyle.application.dto.response.HairStyleResponse;
import com.inq.wishhair.wesharewishhair.hairstyle.application.dto.response.HairStyleSimpleResponse;
import com.inq.wishhair.wesharewishhair.hairstyle.domain.HairStyle;
import com.inq.wishhair.wesharewishhair.hairstyle.domain.HairStyleQueryRepository;
import com.inq.wishhair.wesharewishhair.hairstyle.domain.HairStyleRepository;
import com.inq.wishhair.wesharewishhair.hairstyle.domain.hashtag.Tag;
import com.inq.wishhair.wesharewishhair.hairstyle.application.dto.response.HairStyleResponse;
import com.inq.wishhair.wesharewishhair.hairstyle.application.dto.response.HairStyleSimpleResponse;
import com.inq.wishhair.wesharewishhair.hairstyle.utils.HairRecommendCondition;
import com.inq.wishhair.wesharewishhair.user.domain.entity.User;
import com.inq.wishhair.wesharewishhair.user.application.UserFindService;
import com.inq.wishhair.wesharewishhair.user.domain.entity.User;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Slf4j
public class HairStyleSearchService {

private final HairStyleRepository hairStyleRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.inq.wishhair.wesharewishhair.global.exception.ErrorCode;
import com.inq.wishhair.wesharewishhair.global.exception.WishHairException;
import com.inq.wishhair.wesharewishhair.hairstyle.application.dto.response.WishHairResponse;
import com.inq.wishhair.wesharewishhair.hairstyle.domain.wishhair.WishHair;
import com.inq.wishhair.wesharewishhair.hairstyle.domain.wishhair.WishHairRepository;

import jakarta.persistence.EntityExistsException;
import lombok.RequiredArgsConstructor;

@Service
Expand All @@ -18,55 +17,39 @@ public class WishHairService {

private final WishHairRepository wishHairRepository;

@Transactional
public void executeWish(
private boolean existWishHair(
final Long hairStyleId,
final Long userId
) {
validateDoesNotExistWishHair(hairStyleId, userId);

wishHairRepository.save(WishHair.createWishHair(userId, hairStyleId));
return wishHairRepository.existsByHairStyleIdAndUserId(hairStyleId, userId);
}

@Transactional
public void cancelWish(
final Long hairStyleId,
final Long userId
) {
validateDoesWishHairExist(hairStyleId, userId);

wishHairRepository.deleteByHairStyleIdAndUserId(hairStyleId, userId);
}

public WishHairResponse checkIsWishing(
public boolean executeWish(
final Long hairStyleId,
final Long userId
) {
return new WishHairResponse(existWishHair(hairStyleId, userId));
}

private boolean existWishHair(
final Long hairStyleId,
final Long userId
) {
return wishHairRepository.existsByHairStyleIdAndUserId(hairStyleId, userId);
try {
wishHairRepository.save(WishHair.createWishHair(userId, hairStyleId));
} catch (EntityExistsException e) {
return false;
}
return true;
}

private void validateDoesWishHairExist(
@Transactional
public boolean cancelWish(
final Long hairStyleId,
final Long userId
) {
if (!existWishHair(hairStyleId, userId)) {
throw new WishHairException(ErrorCode.WISH_HAIR_NOT_EXIST);
}
wishHairRepository.deleteByHairStyleIdAndUserId(hairStyleId, userId);
return true;
}

private void validateDoesNotExistWishHair(
public WishHairResponse checkIsWishing(
final Long hairStyleId,
final Long userId
) {
if (existWishHair(hairStyleId, userId)) {
throw new WishHairException(ErrorCode.WISH_HAIR_ALREADY_EXIST);
}
return new WishHairResponse(existWishHair(hairStyleId, userId));
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package com.inq.wishhair.wesharewishhair.hairstyle.application.query;
package com.inq.wishhair.wesharewishhair.hairstyle.domain;

import java.util.List;

import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

import com.inq.wishhair.wesharewishhair.hairstyle.domain.HairStyle;
import com.inq.wishhair.wesharewishhair.hairstyle.utils.HairRecommendCondition;

public interface HairStyleQueryRepository {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package com.inq.wishhair.wesharewishhair.hairstyle.domain.wishhair;

import java.time.LocalDateTime;

import com.inq.wishhair.wesharewishhair.global.auditing.BaseEntity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -22,16 +19,13 @@ public class WishHair extends BaseEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@JoinColumn
private Long hairStyleId;

@JoinColumn
private Long userId;

private WishHair(final Long hairStyleId, final Long userId) {
this.hairStyleId = hairStyleId;
this.userId = userId;
this.createdDate = LocalDateTime.now();
}

//==Factory method==//
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
package com.inq.wishhair.wesharewishhair.hairstyle.infrastructure;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.inq.wishhair.wesharewishhair.hairstyle.domain.wishhair.WishHair;
import com.inq.wishhair.wesharewishhair.hairstyle.domain.wishhair.WishHairRepository;

public interface WishHairJpaRepository extends WishHairRepository, JpaRepository<WishHair, Long> {

@Modifying
@Query("delete from WishHair w where w.hairStyleId = :hairStyleId and w.userId = :userId")
void deleteByHairStyleIdAndUserId(@Param("hairStyleId") Long hairStyleId,
@Param("userId") Long userId);
void deleteByHairStyleIdAndUserId(Long hairStyleId, Long userId);

boolean existsByHairStyleIdAndUserId(Long hairStyleId, Long userId);
}
Loading