Compare commits
1 Commits
main
...
feature-mo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5c27bda82 |
@@ -45,9 +45,11 @@ dependencies {
|
||||
implementation 'org.springframework.security:spring-security-crypto:5.5.2'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-webflux'
|
||||
|
||||
testImplementation 'io.github.javaunit:autoparams:0.2.12'
|
||||
testImplementation 'com.tngtech.archunit:archunit-junit5:0.20.1'
|
||||
testImplementation 'org.mockito:mockito-inline:3.9.0'
|
||||
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.yam.app.account.infrastructure;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
@Slf4j
|
||||
@EnableAsync
|
||||
@Configuration
|
||||
public class AsyncConfiguration implements AsyncConfigurer {
|
||||
|
||||
@Override
|
||||
public Executor getAsyncExecutor() {
|
||||
var executor = new ThreadPoolTaskExecutor();
|
||||
int processors = Runtime.getRuntime().availableProcessors();
|
||||
log.info("processors count {}", processors);
|
||||
executor.setCorePoolSize(processors);
|
||||
executor.setMaxPoolSize(processors * 2);
|
||||
executor.setQueueCapacity(50);
|
||||
executor.setKeepAliveSeconds(60);
|
||||
executor.setThreadNamePrefix("AsyncExecutor-");
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,13 @@ package com.yam.app.account.infrastructure;
|
||||
import com.yam.app.account.domain.RegisterAccountEvent;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thymeleaf.TemplateEngine;
|
||||
import org.thymeleaf.context.Context;
|
||||
|
||||
@Component
|
||||
final class MailManager {
|
||||
class MailManager {
|
||||
|
||||
private final MailDispatcher mailDispatcher;
|
||||
private final TemplateEngine templateEngine;
|
||||
@@ -21,6 +22,7 @@ final class MailManager {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
@Async
|
||||
@EventListener
|
||||
public void handle(RegisterAccountEvent event) {
|
||||
var newAccount = event.getAccount();
|
||||
|
||||
@@ -5,10 +5,8 @@ import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.sli
|
||||
import com.tngtech.archunit.junit.AnalyzeClasses;
|
||||
import com.tngtech.archunit.junit.ArchTest;
|
||||
import com.tngtech.archunit.lang.ArchRule;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
|
||||
@AnalyzeClasses(packagesOf = YouAndMeApplication.class)
|
||||
@Disabled
|
||||
final class CircularDependencyTests {
|
||||
|
||||
@ArchTest
|
||||
|
||||
27
src/test/java/com/yam/app/YouAndMeApplicationTests.java
Normal file
27
src/test/java/com/yam/app/YouAndMeApplicationTests.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.yam.app;
|
||||
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
|
||||
final class YouAndMeApplicationTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("SpringApplication.run() 실행을 Mocking합니다.")
|
||||
void mainShouldStartMyApplication() {
|
||||
try (MockedStatic<SpringApplication> mocked = mockStatic(SpringApplication.class)) {
|
||||
|
||||
mocked.when(
|
||||
() -> SpringApplication.run(YouAndMeApplication.class, "foo"))
|
||||
.thenReturn(null);
|
||||
|
||||
YouAndMeApplication.main(new String[]{"foo"});
|
||||
|
||||
mocked.verify(
|
||||
() -> SpringApplication.run(YouAndMeApplication.class, "foo"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,8 @@
|
||||
package com.yam.app.account.integration;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.yam.app.account.presentation.RegisterAccountRequest;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -14,7 +10,9 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.client.MockMvcWebTestClient;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@@ -28,6 +26,15 @@ final class AccountIntegrationTests {
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
private WebTestClient webTestClient;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.webTestClient = MockMvcWebTestClient
|
||||
.bindTo(mockMvc)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("새로운 계정을 등록하는 회원가입 시나리오")
|
||||
void register_success() throws Exception {
|
||||
@@ -38,18 +45,20 @@ final class AccountIntegrationTests {
|
||||
request.setPassword("password!");
|
||||
|
||||
// Act
|
||||
final var actions = mockMvc.perform(post("/api/accounts")
|
||||
var spec = webTestClient
|
||||
.post()
|
||||
.uri("/api/accounts")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request))
|
||||
);
|
||||
.bodyValue(objectMapper.writeValueAsString(request))
|
||||
.exchange();
|
||||
|
||||
// Assert
|
||||
actions
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").isNumber())
|
||||
.andExpect(jsonPath("$.email").isString())
|
||||
.andExpect(jsonPath("$.nickname").isString());
|
||||
spec
|
||||
.expectStatus().isOk()
|
||||
.expectBody()
|
||||
.jsonPath("$.id").isNumber()
|
||||
.jsonPath("$.email").isNotEmpty()
|
||||
.jsonPath("$.nickname").isNotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package com.yam.app.account.presentation;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.yam.app.account.application.AccountFacade;
|
||||
import org.javaunit.autoparams.AutoSource;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
@@ -16,8 +13,11 @@ import org.junit.jupiter.params.provider.NullAndEmptySource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.client.MockMvcWebTestClient;
|
||||
|
||||
@DisplayName("회원가입 등록 HTTP API")
|
||||
@WebMvcTest(RegisterAccountApi.class)
|
||||
@@ -30,6 +30,15 @@ class RegisterAccountApiTests {
|
||||
@MockBean
|
||||
private AccountFacade accountFacade;
|
||||
|
||||
private WebTestClient webTestClient;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.webTestClient = MockMvcWebTestClient
|
||||
.bindTo(mockMvc)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("회원가입에 적절한 파라미터가 입력되고 회원가입이 성공한다.")
|
||||
void register_success() throws Exception {
|
||||
@@ -43,19 +52,21 @@ class RegisterAccountApiTests {
|
||||
when(accountFacade.register(request)).thenReturn(
|
||||
new AccountResponse(1L, "msolo021015@gmail.com", "rebwon"));
|
||||
|
||||
final var actions = mockMvc.perform(post("/api/accounts")
|
||||
var spec = webTestClient
|
||||
.post()
|
||||
.uri("/api/accounts")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request))
|
||||
);
|
||||
.bodyValue(objectMapper.writeValueAsString(request))
|
||||
.exchange();
|
||||
|
||||
// Assert
|
||||
actions
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id").isNumber())
|
||||
.andExpect(jsonPath("$.email").isString())
|
||||
.andExpect(jsonPath("$.nickname").isString());
|
||||
spec
|
||||
.expectStatus().isOk()
|
||||
.expectBody()
|
||||
.jsonPath("$.id").isNumber()
|
||||
.jsonPath("$.email").isNotEmpty()
|
||||
.jsonPath("$.nickname").isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -68,13 +79,15 @@ class RegisterAccountApiTests {
|
||||
request.setPassword("password!");
|
||||
|
||||
// Act
|
||||
final var actions = mockMvc.perform(post("/api/accounts")
|
||||
.content(objectMapper.writeValueAsString(request))
|
||||
);
|
||||
var spec = webTestClient
|
||||
.post()
|
||||
.uri("/api/accounts")
|
||||
.bodyValue(objectMapper.writeValueAsString(request))
|
||||
.exchange();
|
||||
|
||||
// Assert
|
||||
actions
|
||||
.andExpect(status().isUnsupportedMediaType());
|
||||
spec
|
||||
.expectStatus().isEqualTo(HttpStatus.UNSUPPORTED_MEDIA_TYPE);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@@ -88,16 +101,17 @@ class RegisterAccountApiTests {
|
||||
request.setPassword(arg);
|
||||
|
||||
// Act
|
||||
final var actions = mockMvc.perform(post("/api/accounts")
|
||||
var spec = webTestClient
|
||||
.post()
|
||||
.uri("/api/accounts")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request))
|
||||
);
|
||||
.bodyValue(objectMapper.writeValueAsString(request))
|
||||
.exchange();
|
||||
|
||||
// Assert
|
||||
actions
|
||||
.andDo(print())
|
||||
.andExpect(status().isBadRequest());
|
||||
spec
|
||||
.expectStatus().isBadRequest();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@@ -111,15 +125,16 @@ class RegisterAccountApiTests {
|
||||
request.setPassword(arg);
|
||||
|
||||
// Act
|
||||
final var actions = mockMvc.perform(post("/api/accounts")
|
||||
var spec = webTestClient
|
||||
.post()
|
||||
.uri("/api/accounts")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(request))
|
||||
);
|
||||
.bodyValue(objectMapper.writeValueAsString(request))
|
||||
.exchange();
|
||||
|
||||
// Assert
|
||||
actions
|
||||
.andDo(print())
|
||||
.andExpect(status().isBadRequest());
|
||||
spec
|
||||
.expectStatus().isBadRequest();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user