<aside> 1️⃣ 오류가 생긴 코드
</aside>
import com.jinan.profile.controller.board.BoardController;
import com.jinan.profile.controller.chat.ChatMainController;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;
@Profile("test")
@Import(TestSecurityConfig.class) // 테스트 설정 클래스 적용
@WebMvcTest({
ChatMainController.class,
BoardController.class
})
public abstract class ControllerTestSupport {
}
@DisplayName("[Board] - 컨트롤러 테스트")
class BoardControllerTest extends ControllerTestSupport {
@Autowired private MockMvc mockMvc;
@Autowired private ObjectMapper objectMapper;
@MockBean private BoardRepository boardRepository;
@MockBean private BoardService boardService;
@DisplayName("메인페이지에서는 누구나 모든 게시글을 볼 수 있다.")
@Test
void test() throws Exception {
//given
List<BoardDto> boardDtoList = Arrays.asList(
new BoardDto(1L, "Title 1", "Content 1", 100, 10, LocalDateTime.now(), LocalDateTime.now()),
new BoardDto(2L, "Title 2", "Content 2", 200, 20, LocalDateTime.now(), LocalDateTime.now())
);
when(boardService.selectAllBoardList()).thenReturn(boardDtoList);
//when & then
mockMvc.perform(get("/board/list"))
.andExpect(status().isOk())
.andExpect(view().name("/board/list")) // return하는 view 검증
.andExpect(model().attributeExists("boardList")) // "boardList" 속성이 존재하는지 검증
.andExpect(model().attribute("boardList", Matchers.hasSize(2))) //"boardList" 속성의 크기가 2인지 검증
.andExpect(model().attribute("boardList", Matchers.hasItem(
Matchers.allOf(
Matchers.hasProperty("boardId", Matchers.is(1L)),
Matchers.hasProperty("title", Matchers.is("Title 1")),
Matchers.hasProperty("content", Matchers.is("Content 1")),
Matchers.hasProperty("views", Matchers.is(100)),
Matchers.hasProperty("likes", Matchers.is(10))
)
))); // "boardList" 속성에 특정 조건을 만족하는 항목이 포함되어 있는지 검증
}
}
import com.jinan.profile.domain.board.Board;
import java.time.LocalDateTime;
/**
* DTO for {@link Board}
*/
public record BoardDto(
Long boardId,
String title,
String content,
int views,
int likes,
LocalDateTime createdAt,
LocalDateTime updatedAt
) {
// factory method of 선언
public static BoardDto of(Long boardId, String title, String content, int views, int likes, LocalDateTime createdAt, LocalDateTime updatedAt) {
return new BoardDto(boardId, title, content, views, likes, createdAt, updatedAt);
}
// 서비스 레이어에서 entity를 dto로 변환시켜주는 코드
public static BoardDto fromEntity(Board entity) {
return BoardDto.of(
entity.getId(),
entity.getTitle(),
entity.getContent(),
entity.getViews(),
entity.getLikes(),
entity.getCreatedAt(),
entity.getUpdatedAt()
);
}
}
<aside> 2️⃣ 오류 메시지
</aside>
Model attribute 'boardList'
Expected: a collection containing (hasProperty("boardId", is <1L>) and hasProperty("title", is "Title 1") and hasProperty("content", is "Content 1") and hasProperty("views", is <100>) and hasProperty("likes", is <10>))
but: mismatches were: [hasProperty("boardId", is <1L>) No property "boardId", hasProperty("boardId", is <1L>) No property "boardId"]
java.lang.AssertionError: Model attribute 'boardList'
Expected: a collection containing (hasProperty("boardId", is <1L>) and hasProperty("title", is "Title 1") and hasProperty("content", is "Content 1") and hasProperty("views", is <100>) and hasProperty("likes", is <10>))
but: mismatches were: [hasProperty("boardId", is <1L>) No property "boardId", hasProperty("boardId", is <1L>) No property "boardId"]
<aside> 3️⃣ 오류 파악
</aside>
<aside> 4️⃣ 해결 방안
</aside>
hasProperty
매처를 사용하여 **BoardDto
**의 boardId
속성을 검증하려고 했으나, 해당 속성을 찾을 수 없다는 것을 나타낸다.BoardDto
**가 **record
**로 선언되어 있으므로, **record
**의 컴포넌트는 자동으로 private final 필드로 선언되고, 해당 필드에 대한 public 접근자 메서드가 생성된다. 따라서 hasProperty
매처는 getBoardId()
메서드를 찾으려고 시도할 것이다.record
**에서는 일반적인 getter 메서드 대신 컴포넌트 이름과 동일한 메서드가 생성된다. 예를 들어, boardId
컴포넌트에 대한 접근자 메서드는 **getBoardId()
**가 아니라 **boardId()
**가 된다.hasProperty
대신 다른 방법을 사용해야 한다. 아래는 **BoardDto
**의 boardId
컴포넌트를 검증하는 예시이다.<aside> 5️⃣ 해결 완료
</aside>