Skip to content

Commit

Permalink
Merge pull request #93 from kakao-tech-campus-2nd-step3/test/91
Browse files Browse the repository at this point in the history
test: 누락된 테스트 코드 작성
  • Loading branch information
peeerr authored Nov 6, 2024
2 parents 9ceb1e1 + 69ea6d2 commit 43965da
Show file tree
Hide file tree
Showing 38 changed files with 4,575 additions and 129 deletions.
14 changes: 12 additions & 2 deletions .github/workflows/master_weekly_cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ jobs:
- name: 프로젝트 코드를 CI 서버로 옮겨오기
uses: actions/checkout@v4

- name: Gradle 캐시 설정
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: JDK 21 설치
uses: actions/setup-java@v4
with:
Expand All @@ -39,8 +49,8 @@ jobs:
- name: 빌드로 테스트 수행 및 Jar 파일 생성
run: |
chmod +x ./gradlew
./gradlew clean build
mv build/libs/*SNAPSHOT.jar ./app.jar
./gradlew clean build --build-cache
- run: mv build/libs/*SNAPSHOT.jar ./app.jar

- name: 생성된 Jar 파일 EC2 서버로 전송하기
uses: appleboy/[email protected]
Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/pr_weekly_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ jobs:
- name: 프로젝트 코드를 CI 서버로 옮겨오기
uses: actions/checkout@v4

- name: Gradle 캐시 설정
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: JDK 21 설치
uses: actions/setup-java@v4
with:
Expand All @@ -42,7 +52,7 @@ jobs:
- name: 빌드 테스트 수행
run: |
chmod +x ./gradlew
./gradlew clean build --stacktrace
./gradlew clean build --build-cache --stacktrace
- name: 테스트 수행 결과 보고
uses: EnricoMi/publish-unit-test-result-action@v2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
import com.potatocake.everymoment.entity.Member;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Getter
public class CategoryCreateRequest {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Getter
public class FcmTokenRequest {

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/potatocake/everymoment/entity/Like.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Table(name = "likes")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity
public class Like {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
package com.potatocake.everymoment.controller;

import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.BDDMockito.willDoNothing;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
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.potatocake.everymoment.dto.request.CategoryCreateRequest;
import com.potatocake.everymoment.dto.response.CategoryResponse;
import com.potatocake.everymoment.entity.Member;
import com.potatocake.everymoment.security.MemberDetails;
import com.potatocake.everymoment.service.CategoryService;
import java.util.List;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
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.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;

@WebMvcTest(CategoryController.class)
class CategoryControllerTest {

@Autowired
private MockMvc mockMvc;

@Autowired
private ObjectMapper objectMapper;

@MockBean
private CategoryService categoryService;

@Test
@DisplayName("카테고리 목록이 성공적으로 조회된다.")
void should_ReturnCategories_When_RequestCategories() throws Exception {
// given
Long memberId = 1L;
Member member = Member.builder()
.id(memberId)
.number(1234L)
.nickname("testUser")
.build();
MemberDetails memberDetails = new MemberDetails(member);

List<CategoryResponse> responses = List.of(
CategoryResponse.builder()
.id(1L)
.categoryName("Category 1")
.build(),
CategoryResponse.builder()
.id(2L)
.categoryName("Category 2")
.build()
);

given(categoryService.getCategories(memberId)).willReturn(responses);

// when
ResultActions result = mockMvc.perform(get("/api/categories")
.with(user(memberDetails)));

// then
result.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.message").value("success"))
.andExpect(jsonPath("$.info").isArray())
.andExpect(jsonPath("$.info[0].categoryName").value("Category 1"))
.andExpect(jsonPath("$.info[1].categoryName").value("Category 2"));

then(categoryService).should().getCategories(memberId);
}

@Test
@DisplayName("카테고리가 성공적으로 추가된다.")
void should_CreateCategory_When_ValidInput() throws Exception {
// given
Long memberId = 1L;
Member member = Member.builder()
.id(memberId)
.number(1234L)
.nickname("testUser")
.build();
MemberDetails memberDetails = new MemberDetails(member);

CategoryCreateRequest request = new CategoryCreateRequest("New Category");

willDoNothing().given(categoryService).addCategory(
eq(memberId),
argThat(req -> req.getCategoryName().equals("New Category"))
);

// when
ResultActions result = mockMvc.perform(post("/api/categories")
.with(user(memberDetails))
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)));

// then
result.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.message").value("success"));

then(categoryService).should().addCategory(
eq(memberId),
argThat(req -> req.getCategoryName().equals("New Category"))
);
}

@Test
@DisplayName("카테고리가 성공적으로 수정된다.")
void should_UpdateCategory_When_ValidInput() throws Exception {
// given
Long memberId = 1L;
Long categoryId = 1L;
Member member = Member.builder()
.id(memberId)
.number(1234L)
.nickname("testUser")
.build();
MemberDetails memberDetails = new MemberDetails(member);

CategoryCreateRequest request = new CategoryCreateRequest("Updated Category");

willDoNothing().given(categoryService).updateCategory(
eq(categoryId),
eq(memberId),
argThat(req -> req.getCategoryName().equals("Updated Category"))
);

// when
ResultActions result = mockMvc.perform(patch("/api/categories/{categoryId}", categoryId)
.with(user(memberDetails))
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)));

// then
result.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.message").value("success"));

then(categoryService).should().updateCategory(
eq(categoryId),
eq(memberId),
argThat(req -> req.getCategoryName().equals("Updated Category"))
);
}

@Test
@DisplayName("카테고리가 성공적으로 삭제된다.")
void should_DeleteCategory_When_ValidId() throws Exception {
// given
Long memberId = 1L;
Long categoryId = 1L;
Member member = Member.builder()
.id(memberId)
.number(1234L)
.nickname("testUser")
.build();
MemberDetails memberDetails = new MemberDetails(member);

willDoNothing().given(categoryService).deleteCategory(categoryId, memberId);

// when
ResultActions result = mockMvc.perform(delete("/api/categories/{categoryId}", categoryId)
.with(user(memberDetails))
.with(csrf()));

// then
result.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.message").value("success"));

then(categoryService).should().deleteCategory(categoryId, memberId);
}

@Test
@DisplayName("카테고리명이 누락되면 생성에 실패한다.")
void should_FailToCreate_When_CategoryNameMissing() throws Exception {
// given
Long memberId = 1L;
Member member = Member.builder()
.id(memberId)
.number(1234L)
.nickname("testUser")
.build();
MemberDetails memberDetails = new MemberDetails(member);

CategoryCreateRequest request = new CategoryCreateRequest(); // categoryName 누락

// when
ResultActions result = mockMvc.perform(post("/api/categories")
.with(user(memberDetails))
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)));

// then
result.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value(400));

then(categoryService).shouldHaveNoInteractions();
}

}
Loading

0 comments on commit 43965da

Please sign in to comment.