Skip to content

Commit

Permalink
Merge pull request #26 from Team-Motivoo/hotfix/#25-security_redis_test
Browse files Browse the repository at this point in the history
[FEAT] 테스트 Redis 설정파일 에러 해결
  • Loading branch information
jun02160 authored Jan 10, 2024
2 parents 7c65617 + 3e44013 commit 489c016
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 104 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ build/
!**/src/test/**/build/

application-local.yml
application.yml

**.adoc

Expand Down
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ dependencies {
runtimeOnly 'com.mysql:mysql-connector-j'

// H2 (테스트용)
runtimeOnly 'com.h2database:h2'
testImplementation 'com.h2database:h2'

// Security
Expand Down Expand Up @@ -110,6 +111,11 @@ dependencies {

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

// testcontainers
testImplementation "org.junit.jupiter:junit-jupiter:5.8.1"
testImplementation "org.testcontainers:junit-jupiter:1.16.3"

testImplementation 'org.springframework.boot:spring-boot-starter-test'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public RedisConnectionFactory redisConnectionFactory() {
}

@Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> redisTemplate = new RedisTemplate<>();
public RedisTemplate<String, String> redisTemplate() {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
return redisTemplate;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
package sopt.org.motivooServer.domain.auth.repository;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import static sopt.org.motivooServer.domain.user.exception.UserExceptionType.*;

import java.util.Date;
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.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.oauth2.jwt.JwtException;
import org.springframework.stereotype.Repository;
import sopt.org.motivooServer.domain.user.exception.UserException;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static sopt.org.motivooServer.domain.user.exception.UserExceptionType.TOKEN_EXPIRED;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.RequiredArgsConstructor;
import sopt.org.motivooServer.domain.auth.config.RedisConfig;
import sopt.org.motivooServer.domain.user.exception.UserException;

@Repository
@RequiredArgsConstructor
public class TokenRedisRepository {
private final StringRedisTemplate redisTemplate;
private final ValueOperations<String, String> valueOperations;

private final RedisConfig redisConfig;

@Value("${jwt.refresh-token.expire-length}")
private long refreshTokenValidityInMilliseconds;
Expand All @@ -31,19 +35,20 @@ public class TokenRedisRepository {
@Value("${jwt.token.secret-key}")
private String secretKey;

public TokenRedisRepository(StringRedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
this.valueOperations = redisTemplate.opsForValue();
}


public void saveRefreshToken(String refreshToken, String account) {
RedisTemplate<String, String> redisTemplate = redisConfig.redisTemplate();
ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();

String key = PREFIX_REFRESH + refreshToken;
valueOperations.set(key, account);
redisTemplate.expire(key, refreshTokenValidityInMilliseconds, TimeUnit.SECONDS);
}

public void saveBlockedToken(String accessToken) {
RedisTemplate<String, String> redisTemplate = redisConfig.redisTemplate();
ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();

String key = PREFIX_BLOCKED + accessToken;
valueOperations.set(key, "empty");

Expand All @@ -68,22 +73,34 @@ private Date getExpirationFromToken(String accessToken) {
}

private void setExpirationInRedis(String key, Date expiration) {
RedisTemplate<String, String> redisTemplate = redisConfig.redisTemplate();
ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();

Long now = new Date().getTime();
Long remainTime = expiration.getTime() - now;
redisTemplate.expire(key, remainTime, TimeUnit.SECONDS);
}

public Optional<String> findByRefreshToken(String refreshToken) {
RedisTemplate<String, String> redisTemplate = redisConfig.redisTemplate();
ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();

String key = PREFIX_REFRESH + refreshToken;
return Optional.ofNullable(valueOperations.get(key));
}

public boolean doesTokenBlocked(String accessToken) {
RedisTemplate<String, String> redisTemplate = redisConfig.redisTemplate();
ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();

String key = PREFIX_BLOCKED + accessToken;
return valueOperations.get(key) != null;
}

public void deleteRefreshToken(String refreshToken) {
RedisTemplate<String, String> redisTemplate = redisConfig.redisTemplate();
ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();

String key = PREFIX_REFRESH + refreshToken;
redisTemplate.delete(key);
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
spring:
datasource:
driver-clas-name: com.mysql.cj.jdbc.Driver
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://${DATABASE_ENDPOINT_URL}:3306/${DATABASE_NAME}?serverTimezone=UTC&characterEncoding=UTF-8
username: ${DATABASE_USER}
password: ${DATABASE_PASSWORD}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,13 @@
package sopt.org.motivooServer;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;

import sopt.org.motivooServer.domain.auth.config.CustomJwtAuthenticationEntryPoint;
import sopt.org.motivooServer.domain.auth.config.JwtTokenProvider;
import sopt.org.motivooServer.domain.auth.config.RedisConfig;
import sopt.org.motivooServer.domain.auth.repository.TokenRedisRepository;
import sopt.org.motivooServer.global.util.slack.SlackUtil;

@SpringBootTest
@ActiveProfiles({"local", "deploy"})
//TODO EC2로 application-test.yml도 보내줘야 함!
// @SpringBootTest
class MotivooServerApplicationTests {

@MockBean
private SlackUtil slackUtil;

@MockBean
private JwtTokenProvider jwtTokenProvider;

@MockBean
private CustomJwtAuthenticationEntryPoint customJwtAuthenticationEntryPoint;

@MockBean
private RedisConfig redisConfig;

@MockBean
private TokenRedisRepository tokenRedisRepository;


@Test
void contextLoads() {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@
import sopt.org.motivooServer.domain.auth.config.JwtTokenProvider;
import sopt.org.motivooServer.domain.auth.config.RedisConfig;
import sopt.org.motivooServer.domain.auth.repository.TokenRedisRepository;
import sopt.org.motivooServer.global.config.aws.AWSConfig;
import sopt.org.motivooServer.global.util.s3.S3Service;
import sopt.org.motivooServer.global.util.slack.SlackUtil;

@AutoConfigureMockMvc
@AutoConfigureRestDocs
@ExtendWith({RestDocumentationExtension.class})
@WebMvcTest(properties = "spring.config.location=classpath:/application-local.yml")
@WebMvcTest(properties = "spring.config.location=classpath:/application.yml")
public abstract class BaseControllerTest {

@Autowired
Expand All @@ -38,18 +41,27 @@ public abstract class BaseControllerTest {

@Autowired
protected MockMvc mockMvc;
@MockBean
private RedisConfig redisConfig;

@Autowired
@MockBean
private TokenRedisRepository tokenRedisRepository;


@MockBean
private JwtTokenProvider jwtTokenProvider;

@Autowired
@MockBean
private CustomJwtAuthenticationEntryPoint customJwtAuthenticationEntryPoint;

@Autowired
private RedisConfig redisConfig;
@MockBean
private SlackUtil slackUtil;

@Autowired
private TokenRedisRepository tokenRedisRepository;
@MockBean
private AWSConfig awsConfig;

@MockBean
private S3Service s3Service;

@BeforeEach
void setUp(final RestDocumentationContextProvider restDocumentation) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
import static org.springframework.restdocs.payload.JsonFieldType.*;
import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static sopt.org.motivooServer.global.response.SuccessType.*;

import java.security.Principal;
import static sopt.org.motivooServer.util.ApiDocumentUtil.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand All @@ -16,20 +15,15 @@
import org.springframework.http.MediaType;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import com.epages.restdocs.apispec.ResourceSnippetParameters;

import lombok.extern.slf4j.Slf4j;
import sopt.org.motivooServer.domain.auth.config.CustomJwtAuthenticationEntryPoint;
import sopt.org.motivooServer.domain.auth.config.JwtTokenProvider;
import sopt.org.motivooServer.domain.auth.config.RedisConfig;
import sopt.org.motivooServer.domain.auth.repository.TokenRedisRepository;
import sopt.org.motivooServer.global.healthcheck.HealthCheckController;
import sopt.org.motivooServer.global.response.ApiResponse;
import sopt.org.motivooServer.global.util.slack.SlackUtil;
import sopt.org.motivooServer.util.ApiDocumentUtil;

@Slf4j
@DisplayName("HealthCheckController 테스트")
Expand All @@ -38,23 +32,12 @@ public class HealthCheckControllerTest extends BaseControllerTest {

protected static final String DEFAULT_URL = "/api/health";

@MockBean
private SlackUtil slackUtil;

@MockBean
private JwtTokenProvider jwtTokenProvider;

@MockBean
private CustomJwtAuthenticationEntryPoint customJwtAuthenticationEntryPoint;

@MockBean
private HealthCheckController healthCheckController;

@MockBean
private RedisConfig redisConfig;

@MockBean
private TokenRedisRepository tokenRedisRepository;

@DisplayName("Health Check Controller 테스트")
@Test
Expand All @@ -66,13 +49,13 @@ void healthCheckControllerTest() throws Exception {

// then
ResultActions resultActions = mockMvc.perform(
RestDocumentationRequestBuilders.get(DEFAULT_URL)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
).andDo(
MockMvcRestDocumentation.document("healthCheck",
preprocessRequest(prettyPrint()),
preprocessResponse(prettyPrint()),
RestDocumentationRequestBuilders.get(DEFAULT_URL)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
).andDo(
MockMvcRestDocumentation.document("healthCheck",
getDocumentRequest(),
getDocumentResponse(),
resource(
ResourceSnippetParameters.builder()
.tag("HealthCheck API")
Expand All @@ -88,9 +71,9 @@ void healthCheckControllerTest() throws Exception {
// .responseSchema(Schema.schema("HealthCheckResponse.health"))
.build()
)
)
);
)
);

resultActions.andExpect(MockMvcResultMatchers.status().isOk());
resultActions.andExpect(MockMvcResultMatchers.status().isOk());
}
}
17 changes: 17 additions & 0 deletions src/test/java/sopt/org/motivooServer/util/ApiDocumentUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package sopt.org.motivooServer.util;

import static org.springframework.restdocs.operation.preprocess.Preprocessors.*;

import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor;
import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor;

public interface ApiDocumentUtil {

static OperationRequestPreprocessor getDocumentRequest() {
return preprocessRequest(prettyPrint());
}

static OperationResponsePreprocessor getDocumentResponse() {
return preprocessResponse(prettyPrint());
}
}
22 changes: 0 additions & 22 deletions src/test/resources/application.yml

This file was deleted.

0 comments on commit 489c016

Please sign in to comment.