Skip to content

Commit 0484401

Browse files
committed
feat(vote-paper) register
DummyService initArtistAccount 추가 테스트 환경 MongoDB Connection 수정 Register Vote Paper API 단위 테스트 1차 작성
1 parent 686697e commit 0484401

File tree

15 files changed

+162
-21
lines changed

15 files changed

+162
-21
lines changed

Diff for: build.gradle

+5
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ compileJava.doFirst {
207207
delete file(generated)
208208
}
209209

210+
tasks.withType(JavaCompile).configureEach {
211+
options.encoding = 'UTF-8'
212+
options.compilerArgs << '-parameters'
213+
}
214+
210215
tasks.withType(GenerateSwaggerUI).configureEach {
211216
dependsOn 'openapi3'
212217
}

Diff for: src/main/java/com/tune_fun/v1/TuneFunV1Application.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
56
import org.springframework.cloud.openfeign.EnableFeignClients;
67

7-
@SpringBootApplication
8+
@SpringBootApplication(exclude = {MongoAutoConfiguration.class})
89
@EnableFeignClients
910
public class TuneFunV1Application {
1011

Diff for: src/main/java/com/tune_fun/v1/account/adapter/input/rest/RegisterController.java

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import com.tune_fun.v1.common.hexagon.WebAdapter;
88
import com.tune_fun.v1.common.response.Response;
99
import com.tune_fun.v1.common.response.ResponseMapper;
10-
import com.tune_fun.v1.vote.adapter.input.rest.RegisterType;
1110
import jakarta.validation.Valid;
1211
import lombok.RequiredArgsConstructor;
1312
import org.springframework.http.ResponseEntity;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.tune_fun.v1.account.adapter.input.rest;
2+
3+
public enum RegisterType {
4+
NORMAL, ARTIST
5+
}

Diff for: src/main/java/com/tune_fun/v1/account/application/port/input/usecase/RegisterUseCase.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package com.tune_fun.v1.account.application.port.input.usecase;
22

3+
import com.tune_fun.v1.account.adapter.input.rest.RegisterType;
34
import com.tune_fun.v1.account.application.port.input.command.AccountCommands;
45
import com.tune_fun.v1.account.domain.value.RegisterResult;
5-
import com.tune_fun.v1.vote.adapter.input.rest.RegisterType;
66

77
@FunctionalInterface
88
public interface RegisterUseCase {

Diff for: src/main/java/com/tune_fun/v1/account/application/service/RegisterService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.tune_fun.v1.account.application.service;
22

3+
import com.tune_fun.v1.account.adapter.input.rest.RegisterType;
34
import com.tune_fun.v1.account.application.port.input.command.AccountCommands;
45
import com.tune_fun.v1.account.application.port.input.usecase.RegisterUseCase;
56
import com.tune_fun.v1.account.application.port.output.LoadAccountPort;
@@ -13,7 +14,6 @@
1314
import com.tune_fun.v1.common.exception.CommonApplicationException;
1415
import com.tune_fun.v1.common.hexagon.UseCase;
1516
import com.tune_fun.v1.common.util.StringUtil;
16-
import com.tune_fun.v1.vote.adapter.input.rest.RegisterType;
1717
import lombok.RequiredArgsConstructor;
1818
import org.jetbrains.annotations.NotNull;
1919
import org.springframework.security.crypto.password.PasswordEncoder;

Diff for: src/main/java/com/tune_fun/v1/vote/adapter/input/rest/RegisterType.java

-5
This file was deleted.

Diff for: src/main/java/com/tune_fun/v1/vote/adapter/input/rest/VotePaperController.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ public class VotePaperController {
2626

2727
@PreAuthorize("hasRole('ARTIST')")
2828
@PostMapping(value = Uris.REGISTER_VOTE_PAPER)
29-
public ResponseEntity<Response<?>> registerVoteArticle(@Valid @RequestBody final VotePaperCommands.Register command,
30-
@CurrentUser final User user) {
29+
public ResponseEntity<Response<?>> registerVotePaper(@Valid @RequestBody final VotePaperCommands.Register command,
30+
@CurrentUser final User user) {
3131
registerVotePaperUseCase.register(command, user);
3232
return responseMapper.ok();
3333
}

Diff for: src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePaperRepository.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
public interface VotePaperRepository extends MongoRepository<VotePaperMongoEntity, String> {
99

10-
Optional<VotePaperMongoEntity> findByVoteEndAtBeforeAndAuthor(LocalDateTime voteEndAt, String author);
10+
Optional<VotePaperMongoEntity> findByVoteEndAtAfterAndAuthor(LocalDateTime voteEndAt, String author);
1111

12-
Optional<VotePaperMongoEntity> findByVoteEndAtBeforeAndId(LocalDateTime voteEndAt, String id);
12+
Optional<VotePaperMongoEntity> findByVoteEndAtAfterAndId(LocalDateTime voteEndAt, String id);
1313

1414
}

Diff for: src/main/java/com/tune_fun/v1/vote/adapter/output/persistence/VotePersistenceAdapter.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ public void saveVoteChoice(final String votePaperId, final Set<SaveVoteChoice> b
5454
}
5555

5656
public Optional<VotePaperMongoEntity> findAvailableVotePaperById(final String id) {
57-
return votePaperRepository.findByVoteEndAtBeforeAndId(now(), id);
57+
return votePaperRepository.findByVoteEndAtAfterAndId(now(), id);
5858
}
5959

6060
public Optional<VotePaperMongoEntity> findAvailableVotePaperByAuthor(final String username) {
61-
return votePaperRepository.findByVoteEndAtBeforeAndAuthor(now(), username);
61+
return votePaperRepository.findByVoteEndAtAfterAndAuthor(now(), username);
6262
}
6363

6464
}

Diff for: src/main/java/com/tune_fun/v1/vote/application/service/RegisterVotePaperService.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,22 @@ public void register(final VotePaperCommands.Register command, final User user)
4545
saveVoteChoiceByRegisteredVotePaper(command, registeredVotePaper);
4646

4747
// TODO : Scheduling 정책 수립
48-
ProduceVotePaperUploadEvent produceVotePaperUploadEventBehavior = getProduceVotePaperUploadEventBehavior(registeredVotePaper);
49-
produceVotePaperUploadEventPort.produceVotePaperUploadEvent(produceVotePaperUploadEventBehavior);
48+
// ProduceVotePaperUploadEvent produceVotePaperUploadEventBehavior = getProduceVotePaperUploadEventBehavior(registeredVotePaper);
49+
// produceVotePaperUploadEventPort.produceVotePaperUploadEvent(produceVotePaperUploadEventBehavior);
5050
}
5151

5252
public void validateRegistrableVotePaperCount(final User user) {
5353
if (loadVotePaperPort.loadRegisteredVotePaper(user.getUsername()).isPresent())
5454
throw new CommonApplicationException(VOTE_POLICY_ONE_VOTE_PAPER_PER_USER);
5555
}
5656

57+
@Transactional
5758
public RegisteredVotePaper saveVotePaper(VotePaperCommands.Register command) {
5859
SaveVotePaper saveVotePaperBehavior = voteBehaviorMapper.saveVotePaper(command);
5960
return saveVotePaperPort.saveVotePaper(saveVotePaperBehavior);
6061
}
6162

63+
@Transactional
6264
public void saveVoteChoiceByRegisteredVotePaper(VotePaperCommands.Register command, RegisteredVotePaper registeredVotePaper) {
6365
Set<SaveVoteChoice> saveVoteChoicesBehavior = voteBehaviorMapper.saveVoteChoice(command.offers());
6466
saveVoteChoicePort.saveVoteChoice(registeredVotePaper.id(), saveVoteChoicesBehavior);

Diff for: src/main/resources/application-test_standalone.yml

+10-1
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,13 @@ kms:
107107
encrypt-key-arn:
108108

109109
otp:
110-
validity: 3m
110+
validity: 3m
111+
112+
logging:
113+
level:
114+
org:
115+
springframework:
116+
data:
117+
mongodb:
118+
core:
119+
MongoTemplate: DEBUG

Diff for: src/test/java/com/tune_fun/v1/base/integration/TestContainersConfig.java

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package com.tune_fun.v1.base.integration;
22

3+
import com.mongodb.ConnectionString;
4+
import com.mongodb.MongoClientSettings;
5+
import io.micrometer.core.instrument.MeterRegistry;
6+
import io.micrometer.core.instrument.binder.mongodb.MongoMetricsCommandListener;
7+
import io.micrometer.core.instrument.binder.mongodb.MongoMetricsConnectionPoolListener;
38
import org.springframework.boot.devtools.restart.RestartScope;
49
import org.springframework.boot.test.context.TestConfiguration;
510
import org.springframework.context.annotation.Bean;
611
import org.springframework.context.annotation.Profile;
12+
import org.springframework.data.mongodb.core.MongoClientFactoryBean;
713
import org.springframework.test.context.DynamicPropertyRegistry;
814
import org.springframework.test.context.DynamicPropertySource;
915
import org.testcontainers.containers.GenericContainer;
@@ -79,8 +85,9 @@ static void setProperties(DynamicPropertyRegistry registry) {
7985
registry.add("spring.datasource.username", () -> POSTGRES_CONTAINER.getUsername());
8086
registry.add("spring.datasource.password", () -> POSTGRES_CONTAINER.getPassword());
8187

82-
registry.add("spring.data.mongodb.host", () -> MONGODB_CONTAINER.getHost());
83-
registry.add("spring.data.mongodb.port", () -> MONGODB_CONTAINER.getFirstMappedPort());
88+
// registry.add("spring.data.mongodb.host", () -> MONGODB_CONTAINER.getHost());
89+
// registry.add("spring.data.mongodb.port", () -> MONGODB_CONTAINER.getFirstMappedPort());
90+
registry.add("spring.data.mongodb.uri", () -> MONGODB_CONTAINER.getReplicaSetUrl());
8491
registry.add("spring.data.mongodb.username", () -> "test");
8592
registry.add("spring.data.mongodb.password", () -> "test");
8693

@@ -98,4 +105,20 @@ public DataSource dataSource() {
98105
.build();
99106
}
100107

108+
@Bean
109+
public MongoClientFactoryBean mongoClientFactoryBean(MeterRegistry meterRegistry) {
110+
MongoClientFactoryBean mongoClientFactoryBean = new MongoClientFactoryBean();
111+
112+
mongoClientFactoryBean.setConnectionString(new ConnectionString(MONGODB_CONTAINER.getReplicaSetUrl()));
113+
114+
MongoClientSettings settings = MongoClientSettings.builder()
115+
.addCommandListener(new MongoMetricsCommandListener(meterRegistry))
116+
.applyToConnectionPoolSettings(builder ->
117+
builder.addConnectionPoolListener(new MongoMetricsConnectionPoolListener(meterRegistry)))
118+
.build();
119+
mongoClientFactoryBean.setMongoClientSettings(settings);
120+
121+
return mongoClientFactoryBean;
122+
}
123+
101124
}

Diff for: src/test/java/com/tune_fun/v1/dummy/DummyService.java

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.tune_fun.v1.dummy;
22

33

4+
import com.tune_fun.v1.account.adapter.input.rest.RegisterType;
45
import com.tune_fun.v1.account.adapter.output.persistence.AccountJpaEntity;
56
import com.tune_fun.v1.account.adapter.output.persistence.AccountPersistenceAdapter;
67
import com.tune_fun.v1.account.adapter.output.persistence.device.DeviceJpaEntity;
@@ -20,7 +21,6 @@
2021
import com.tune_fun.v1.otp.domain.behavior.LoadOtp;
2122
import com.tune_fun.v1.otp.domain.value.CurrentDecryptedOtp;
2223
import com.tune_fun.v1.otp.domain.value.VerifyResult;
23-
import com.tune_fun.v1.vote.adapter.input.rest.RegisterType;
2424
import lombok.Getter;
2525
import org.springframework.beans.factory.annotation.Autowired;
2626
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -97,6 +97,22 @@ public void initAccount() throws NoSuchAlgorithmException {
9797
.orElseThrow(() -> new RuntimeException("initUser 실패"));
9898
}
9999

100+
@Transactional
101+
public void initArtistAccount() throws NoSuchAlgorithmException {
102+
defaultUsername = StringUtil.randomAlphanumeric(10, 15);
103+
defaultPassword = StringUtil.randomAlphaNumericSymbol(15, 20);
104+
defaultEmail = StringUtil.randomAlphabetic(7) + "@" + StringUtil.randomAlphabetic(5) + ".com";
105+
String nickname = StringUtil.randomAlphabetic(5);
106+
107+
AccountCommands.Notification notification = new AccountCommands.Notification(true, true, true);
108+
AccountCommands.Register command = new AccountCommands.Register(defaultUsername, defaultPassword, defaultEmail, nickname, notification);
109+
110+
registerUseCase.register(RegisterType.ARTIST, command);
111+
112+
defaultAccount = accountPersistenceAdapter.loadAccountByUsername(defaultUsername)
113+
.orElseThrow(() -> new RuntimeException("initUser 실패"));
114+
}
115+
100116
@Transactional
101117
public void login(final AccountJpaEntity account) throws NoSuchAlgorithmException {
102118
defaultAccessToken = generateAccessTokenUseCase.generateAccessToken(account);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.tune_fun.v1.vote.adapter.input.rest;
2+
3+
import com.tune_fun.v1.base.ControllerBaseTest;
4+
import com.tune_fun.v1.common.config.Uris;
5+
import com.tune_fun.v1.common.response.MessageCode;
6+
import com.tune_fun.v1.dummy.DummyService;
7+
import com.tune_fun.v1.vote.application.port.input.command.VotePaperCommands;
8+
import org.junit.jupiter.api.DisplayName;
9+
import org.junit.jupiter.api.Order;
10+
import org.junit.jupiter.api.Test;
11+
import org.springframework.beans.factory.annotation.Autowired;
12+
import org.springframework.restdocs.payload.FieldDescriptor;
13+
14+
import java.util.List;
15+
import java.util.Set;
16+
17+
import static com.epages.restdocs.apispec.ResourceDocumentation.resource;
18+
import static com.epages.restdocs.apispec.ResourceSnippetParameters.builder;
19+
import static com.tune_fun.v1.base.doc.RestDocsConfig.constraint;
20+
import static java.time.LocalDateTime.now;
21+
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
22+
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
23+
import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders;
24+
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
25+
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
26+
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
27+
28+
class VotePaperControllerIT extends ControllerBaseTest {
29+
30+
@Autowired
31+
private DummyService dummyService;
32+
33+
@Test
34+
@Order(1)
35+
@DisplayName("투표 게시물 등록, 성공")
36+
void registerVotePaperSuccess() throws Exception {
37+
dummyService.initArtistAccount();
38+
39+
dummyService.login(dummyService.getDefaultAccount());
40+
String accessToken = dummyService.getDefaultAccessToken();
41+
42+
Set<VotePaperCommands.Offer> offers = Set.of(
43+
new VotePaperCommands.Offer("Love Lee", "AKMU", List.of("R&B", "Soul"),
44+
300000, "2024-04-28"),
45+
new VotePaperCommands.Offer("Dolphin", "오마이걸", List.of("Dance", "Pop"),
46+
200000, "2020-04-27")
47+
);
48+
VotePaperCommands.Register command = new VotePaperCommands.Register("First Vote Paper", "test",
49+
"deny-add-choices", now().plusDays(1), now().plusDays(2), offers);
50+
51+
FieldDescriptor[] requestDescriptors = {
52+
fieldWithPath("title").description("투표 게시물 제목").attributes(constraint("NOT BLANK")),
53+
fieldWithPath("content").description("투표 게시물 내용").attributes(constraint("NOT BLANK")),
54+
fieldWithPath("option").description("투표 종류").attributes(constraint("NOT BLANK")),
55+
fieldWithPath("startAt").description("투표 시작 시간").attributes(constraint("NOT NULL & FUTURE & BEFORE(endAt)")),
56+
fieldWithPath("endAt").description("투표 종료 시간").attributes(constraint("NOT NULL & FUTURE & AFTER(startAt)")),
57+
fieldWithPath("offers").description("투표 선택지 목록").attributes(constraint("NOT EMPTY")),
58+
fieldWithPath("offers[].name").description("노래명").attributes(constraint("NOT BLANK")),
59+
fieldWithPath("offers[].artistName").description("가수명").attributes(constraint("NOT BLANK")),
60+
fieldWithPath("offers[].genres").description("장르").attributes(constraint("NOT EMPTY")),
61+
fieldWithPath("offers[].durationMs").description("재생 시간(ms)").attributes(constraint("NOT NULL & POSITIVE")),
62+
fieldWithPath("offers[].releaseDate").description("발매일").attributes(constraint("NOT BLANK"))
63+
};
64+
65+
mockMvc.perform(
66+
post(Uris.REGISTER_VOTE_PAPER)
67+
.header(AUTHORIZATION, bearerToken(accessToken))
68+
.content(toJson(command))
69+
.contentType(APPLICATION_JSON_VALUE)
70+
)
71+
.andExpectAll(baseAssertion(MessageCode.SUCCESS))
72+
.andDo(
73+
restDocs.document(
74+
requestHeaders(authorizationHeader),
75+
requestFields(requestDescriptors),
76+
resource(
77+
builder().
78+
description("투표 게시물 등록").
79+
requestFields(requestDescriptors)
80+
.build()
81+
)
82+
)
83+
);
84+
}
85+
86+
}

0 commit comments

Comments
 (0)