Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 4 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew

- name: Clean Gradle Cache (Optional but good)
- name: Clean Gradle Cache
run: ./gradlew clean --refresh-dependencies
- name: Test And Build with Gradle (Debug Mode)

- name: Test And Build with Gradle
env:
JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }}
run: ./gradlew build --stacktrace --info -Dspring.profiles.active=ci
run: ./gradlew build -Dspring.profiles.active=ci

1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.redisson:redisson:3.23.5'

testImplementation 'org.mockito:mockito-inline:5.2.0'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.example.eightyage.domain.product.entity.Product;
import com.example.eightyage.domain.product.entity.ProductImage;
import com.example.eightyage.domain.product.repository.ProductImageRepository;
import com.example.eightyage.domain.product.repository.ProductRepository;
import com.example.eightyage.global.exception.NotFoundException;
import com.example.eightyage.global.exception.ProductImageUploadException;
import lombok.RequiredArgsConstructor;
Expand All @@ -14,9 +13,8 @@
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.UUID;

@Service
Expand All @@ -27,11 +25,8 @@ public class ProductImageService {
private final ProductImageRepository productImageRepository;
private final ProductService productService;

@Value("${aws.s3.bucket}")
private String bucket;

@Value("${aws.region}")
private String region;
private static final String BUCKET_NAME = "my-gom-bucket";
private static final String REGION = "ap-northeast-2";

// 제품 이미지 업로드
@Transactional
Expand All @@ -42,15 +37,15 @@ public String uploadImage(Long productId, MultipartFile file) {
// S3에 업로드
s3Client.putObject(
PutObjectRequest.builder()
.bucket(bucket)
.bucket(BUCKET_NAME)
.key(fileName)
.contentType(file.getContentType())
.build(),
RequestBody.fromInputStream(file.getInputStream(), file.getSize())
);

// S3 이미지 URL 생성
String imageUrl = String.format("https://%s.s3.%s.amazonaws.com/%s", bucket, region, fileName);
String imageUrl = String.format("https://%s.s3.%s.amazonaws.com/%s", BUCKET_NAME, REGION, fileName);

// DB 저장
Product product = productService.findProductByIdOrElseThrow(productId);
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/com/example/eightyage/global/config/S3Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@
@Configuration
public class S3Config {

@Value("${aws.region}")
private String region;
private static final String REGION = "ap-northeast-2";

@Value("${aws.credentials.access-key}")
@Value("${aws.access-key}")
private String accessKey;

@Value("${aws.credentials.secret-key}")
@Value("${aws.secret-key}")
private String secretKey;


@Bean
public S3Client s3Client() {
return S3Client.builder()
.region(Region.of(region))
.region(Region.of(REGION))
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(accessKey, secretKey)
))
Expand Down
21 changes: 10 additions & 11 deletions src/main/resources/application-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,26 @@ server:

spring:
datasource:
url: jdbc:mysql://mysql:3306/team8_test
url: jdbc:mysql://localhost:3306/team8_test
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver

jpa:
hibernate:
ddl-auto: create
ddl-auto: update
properties:
hibernate:
dialect: org.hibernate.dialect.MySQLDialect
show_sql: true
format_sql: true

cloud:
aws:
credentials:
access-key: ${AWS_ACCESS_KEY}
secret-key: ${AWS_SECRET_KEY}

jwt:
secret:
key: ${JWT_SECRET_KEY}

aws:
credentials:
access-key: ${AWS_ACCESS_KEY}
secret-key: ${AWS_SECRET_KEY}
region: ap-northeast-2
s3:
bucket: my-gom-bucket
key: ${JWT_SECRET_KEY}
24 changes: 13 additions & 11 deletions src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
spring:
config:
import: optional:file:.env[.properties]

cloud:
aws:
credentials:
access-key: ${AWS_ACCESS_KEY}
secret-key: ${AWS_SECRET_KEY}
region:
static: ap-northeast-2
s3:
bucket: my-gom-bucket

aws:
credentials:
access-key: ${AWS_ACCESS_KEY}
secret-key: ${AWS_SECRET_KEY}
region: ap-northeast-2
s3:
bucket: my-gom-bucket
datasource:
url: ${DB_URL}
username: ${DB_USER}
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver

data:
redis:
host: localhost
port: 6379
34 changes: 1 addition & 33 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,9 @@ server:
session:
timeout: 1800

spring:
config:
import: optional:file:.env[.properties]

application:
name: eightyage

datasource:
url: ${DB_URL}
username: ${DB_USER}
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver

jpa:
hibernate:
ddl-auto: update
Expand All @@ -32,29 +22,7 @@ spring:
use_sql_comments: true
dialect: org.hibernate.dialect.MySQLDialect

# cloud:
# aws:
# credentials:
# access-key: ${S3_ACCESS_KEY}
# secret-key: ${S3_SECRET_KEY}
# region:
# static: ap-northeast-2
# s3:
# bucket: ${S3_BUCKET}
#
#aws:
# credentials:
# access-key: ${S3_ACCESS_KEY}
# secret-key: ${S3_SECRET_KEY}
# region: ap-northeast-2
# s3:
# bucket: ${S3_BUCKET}

data:
redis:
host: ${REDIS_HOST}
port: 6379

jwt:
secret:
key: ${JWT_SECRET_KEY}

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.eightyage.domain.product.service;

import com.example.eightyage.domain.product.category.Category;
import com.example.eightyage.domain.product.entity.Product;
import com.example.eightyage.domain.product.entity.ProductImage;
import com.example.eightyage.domain.product.repository.ProductImageRepository;
Expand All @@ -13,17 +14,16 @@
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;

import java.util.Optional;
import java.util.function.Consumer;


import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class ProductImageServiceTest {
Expand All @@ -45,43 +45,53 @@ class ProductImageServiceTest {

private MockMultipartFile mockFile;

private Product mockProduct;

@BeforeEach
void setUp(){
mockFile = new MockMultipartFile(
"file",
"tesst.jpg",
"test.jpg",
"image/jpeg",
"test image content".getBytes()
);

ReflectionTestUtils.setField(productImageService, "bucket", "test-bucket");
ReflectionTestUtils.setField(productImageService, "region", "us-west-2");
mockProduct = Product.builder()
.name("Test Product")
.category(Category.SKINCARE)
.content("This is test product.")
.price(10000)
.build();

ReflectionTestUtils.setField(mockProduct, "id", 1L);
}

@Test
void 이미지_업로드_성공(){
void 이미지_업로드_성공() {
// given
Long productId = 1L;
String bucket = "test-bucket";
String region = "us-west-2";
String expectedImageUrl = String.format("https://%s.s3.%s.amazonaws.com/", bucket, region);
given(productService.findProductByIdOrElseThrow(productId)).willReturn(mockProduct);

ProductImage mockProductImage = mock(ProductImage.class);
given(productImageRepository.save(any(ProductImage.class))).willReturn(mockProductImage);

given(productImageRepository.save(any())).willReturn(productImage);
when(s3Client.putObject(any(PutObjectRequest.class), any(RequestBody.class)))
.thenReturn(PutObjectResponse.builder().build());

// when
String imageUrl = productImageService.uploadImage(productId, mockFile);

// then
assertTrue(imageUrl.startsWith(expectedImageUrl));
assertNotNull(imageUrl);
assertTrue(imageUrl.startsWith("https://my-gom-bucket.s3.ap-northeast-2.amazonaws.com/"));
}


@Test
void 이미지_삭제_성공(){
// given
Long imageId = 1L;
String imageUrl = "imageUrl-example";

given(productImageRepository.findById(any())).willReturn(Optional.of(productImage));
given(productImageRepository.findById(imageId)).willReturn(Optional.of(productImage));

// when
productImageService.deleteImage(imageId);
Expand Down