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

[Be/test] 식사 등록하는 API 테스트 #367

Merged
merged 9 commits into from
Jul 10, 2024
2 changes: 2 additions & 0 deletions BE/exceed/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ dependencies {
testImplementation "org.testcontainers:mariadb:1.19.8"
testImplementation "org.testcontainers:testcontainers:1.19.8"
testImplementation "org.testcontainers:junit-jupiter:1.19.8"
testImplementation "org.testcontainers:localstack:1.19.8"



// querydsl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;

@Configuration
@Profile("!test")
public class S3Config {

@Value("${cloud.aws.credentials.access-key}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ses.SesAsyncClient;

@Configuration
@Profile("!test")
public class SesConfig {

@Value("${cloud.aws.credentials.access-key}")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
package com.gaebaljip.exceed.food.adapter.out;

import java.time.LocalDate;
import java.util.List;

import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.stereotype.Component;

import com.gaebaljip.exceed.dto.PageableFoodDTO;
import com.gaebaljip.exceed.food.application.port.out.FoodPort;
import com.gaebaljip.exceed.food.domain.Food;
import com.gaebaljip.exceed.member.adapter.out.persistence.MemberEntity;
import com.gaebaljip.exceed.member.exception.MemberNotFoundException;

Expand All @@ -21,28 +15,12 @@
public class FoodsPersistenceAdapter implements FoodPort {

private final FoodRepository foodRepository;
private final QueryDslFoodRepository queryDslFoodRepository;
private final FoodConverter foodConverter;

@Override
public List<Food> query(Long memberId, LocalDate date) {
return null;
}

@Override
public List<FoodEntity> query(List<Long> foodIds) {
public List<FoodEntity> queryAllEntities(List<Long> foodIds) {
return foodRepository.findAllById(foodIds);
}

@Override
public Slice<Food> query(String lastFoodName, int size, String keyword) {
PageableFoodDTO pageableFoodDTO =
queryDslFoodRepository.findPageableFood(lastFoodName, size, keyword);
PageRequest pageRequest = PageRequest.of(0, pageableFoodDTO.size());
List<Food> foods = foodConverter.toModels(pageableFoodDTO.foodEntities());
return new SliceImpl<>(foods, pageRequest, pageableFoodDTO.hasNext());
}

@Override
public FoodEntity command(FoodEntity foodEntity) {
return foodRepository.save(foodEntity);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
package com.gaebaljip.exceed.food.application.port.out;

import java.time.LocalDate;
import java.util.List;

import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Component;

import com.gaebaljip.exceed.food.adapter.out.FoodEntity;
import com.gaebaljip.exceed.food.domain.Food;
import com.gaebaljip.exceed.member.adapter.out.persistence.MemberEntity;

@Component
public interface FoodPort {

List<Food> query(Long memberId, LocalDate date);

List<FoodEntity> query(List<Long> foodIds);

Slice<Food> query(String lastFoodName, int size, String keyword);
List<FoodEntity> queryAllEntities(List<Long> foodIds);

FoodEntity command(FoodEntity foodEntity);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package com.gaebaljip.exceed.meal.application;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import javax.transaction.Transactional;

import org.springframework.stereotype.Service;

import com.gaebaljip.exceed.dto.EatMealFoodDTO;
import com.gaebaljip.exceed.food.adapter.out.FoodEntity;
import com.gaebaljip.exceed.food.application.port.out.FoodPort;
import com.gaebaljip.exceed.meal.adapter.out.MealEntity;
Expand All @@ -17,6 +14,8 @@
import com.gaebaljip.exceed.meal.application.port.in.EatMealUsecase;
import com.gaebaljip.exceed.meal.application.port.out.MealFoodPort;
import com.gaebaljip.exceed.meal.application.port.out.MealPort;
import com.gaebaljip.exceed.meal.exception.InvalidGException;
import com.gaebaljip.exceed.meal.exception.InvalidMultipleAndGException;
import com.gaebaljip.exceed.meal.exception.InvalidMultipleException;
import com.gaebaljip.exceed.member.adapter.out.persistence.MemberEntity;
import com.gaebaljip.exceed.member.application.port.out.MemberPort;
Expand Down Expand Up @@ -48,14 +47,9 @@ public class EatMealService implements EatMealUsecase {
@Override
@Transactional
public Long execute(EatMealCommand command) {
validateMultiples(
command.eatMealFoodDTOS().stream()
.map(EatMealFoodDTO::multiple)
.filter(Objects::nonNull)
.mapToDouble(Double::doubleValue)
.toArray());
validateGAndMultiple(command);
List<FoodEntity> foodEntities =
foodPort.query(
foodPort.queryAllEntities(
command.eatMealFoodDTOS().stream()
.mapToLong(eatMealFood -> eatMealFood.foodId())
.boxed()
Expand All @@ -69,13 +63,32 @@ public Long execute(EatMealCommand command) {
return mealEntity.getId();
}

private void validateMultiples(double[] multiple) {
Arrays.stream(multiple).forEach(value -> validateMultiple(value));
private void validateGAndMultiple(EatMealCommand command) {
command.eatMealFoodDTOS()
.forEach(
dto -> {
if ((dto.multiple() != null && dto.g() != null)
|| (dto.multiple() == null && dto.g() == null)) {
throw InvalidMultipleAndGException.EXCEPTION;
}
if (dto.multiple() != null) {
validateMultiple(dto.multiple());
}
if (dto.g() != null) {
validateG(dto.g());
}
});
}

private void validateMultiple(double multiple) {
if (multiple <= 0 || multiple > 100) {
throw InvalidMultipleException.EXECPTION;
}
}

private void validateG(int g) {
if (g <= 0) {
throw InvalidGException.EXCEPTION;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public class EatMealExceptionDocs implements SwaggerExampleExceptions {
@ExplainError("0인분 이하거나 100인분 초과일 경우 ")
public EatCeedException _0인분_이하거나_100인분_초과일_경우 = InvalidMultipleException.EXECPTION;

@ExplainError("g가 0이하일 경우")
public EatCeedException g가_0이하일_경우 = InvalidMultipleException.EXECPTION;

@ExplainError("Food를 찾지 못했을 때")
public EatCeedException Food를_찾지_못했을_경우 = FoodNotFoundException.Exception;

Expand All @@ -26,4 +29,8 @@ public class EatMealExceptionDocs implements SwaggerExampleExceptions {

@ExplainError("회원이 존재하지 않을 때")
public EatCeedException 회원이_없을_때 = MemberNotFoundException.EXECPTION;

@ExplainError("식사 등록 시 multiple과 g가 동시에 null이거나 동시에 null이 아닐 때")
public EatCeedException multiple은_null이_아니고_g는_null이어야_하거나_multiple은_null이고_g는_null이_아니어야_합니다 =
InvalidMultipleException.EXECPTION;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gaebaljip.exceed.meal.exception;

import com.gaebaljip.exceed.common.exception.EatCeedException;

public class InvalidGException extends EatCeedException {

public static final EatCeedException EXCEPTION = new InvalidGException();

public InvalidGException() {
super(MealError.INVALID_G);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.gaebaljip.exceed.meal.exception;

import com.gaebaljip.exceed.common.exception.EatCeedException;

import lombok.Getter;

@Getter
public class InvalidMultipleAndGException extends EatCeedException {
public static final EatCeedException EXCEPTION = new InvalidMultipleAndGException();

private InvalidMultipleAndGException() {
super(MealError.INVALID_MULTIPLE_AND_G);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ public enum MealError implements BaseError {
EXTENTION_NOT_ALLOWED(400, "4452", "이미지의 확장자는 jpg, jpeg, png만 가능합니다."),
INSUFFICIENT_MEALS(400, "6000", "하루 식사는 최소 한 끼 이상 제공되어야 합니다."),
INVALID_MULTIPLE(400, "4449", "0인분보다 커야하고, 100인분보다 작아야합니다."),
NOT_SAME_DATE(400, "6001", "하루 식사는 같은 날짜입니다.");
NOT_SAME_DATE(400, "6001", "하루 식사는 같은 날짜입니다."),
INVALID_MULTIPLE_AND_G(
400,
"6002",
"'multiple'은 null이 아니고 'g'는 null이어야 하거나, 'multiple'은 null이고 'g'는 null이 아니어야 합니다."),
INVALID_G(400, "6002", "g은 1 이상이어야합니다.");

private final Integer status;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.gaebaljip.exceed.common;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.junit.jupiter.api.extension.ExtendWith;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(S3BucketInitializer.class)
public @interface InitializeS3Bucket {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.gaebaljip.exceed.common;

import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.utility.DockerImageName;
import org.testcontainers.utility.MountableFile;

public class S3BucketInitializer implements BeforeAllCallback {

private static final DockerImageName LOCALSTACK_IMAGE =
DockerImageName.parse("localstack/localstack:3.3");
private static final LocalStackContainer localStackContainer =
new LocalStackContainer(LOCALSTACK_IMAGE)
.withCopyFileToContainer(
MountableFile.forClasspathResource("init-s3-bucket.sh", 0744),
"/etc/localstack/init/ready.d/init-s3-bucket.sh")
.withServices(LocalStackContainer.Service.S3)
.waitingFor(Wait.forLogMessage(".*Executed init-s3-bucket.sh.*", 1));

// Bucket name as configured in src/test/resources/init-s3-bucket.sh
private static final String BUCKET_NAME = "reflectoring-bucket";

@Override
public void beforeAll(final ExtensionContext context) {
localStackContainer.start();
addConfigurationProperties();
}

private void addConfigurationProperties() {
System.setProperty(
"spring.cloud.aws.credentials.access-key", localStackContainer.getAccessKey());
System.setProperty(
"spring.cloud.aws.credentials.secret-key", localStackContainer.getSecretKey());
System.setProperty("spring.cloud.aws.s3.region", localStackContainer.getRegion());
System.setProperty(
"spring.cloud.aws.s3.endpoint", localStackContainer.getEndpoint().toString());

System.setProperty("io.reflectoring.aws.s3.bucket-name", BUCKET_NAME);
}

public static String bucketName() {
return BUCKET_NAME;
}
}

This file was deleted.

This file was deleted.

Loading
Loading