스프링과 JPA 기반 웹 애플리케이션 개발 #45 관심 주제 테스트

Jake Seo·2021년 6월 9일
0

스프링과 JPA 기반 웹 애플리케이션 개발 #45 관심 주제 테스트

해당 내용은 인프런, 스프링과 JPA 기반 웹 애플리케이션 개발의 강의 내용을 바탕으로 작성된 내용입니다.

강의를 학습하며 요약한 내용을 출처를 표기하고 블로깅 또는 문서로 공개하는 것을 허용합니다 라는 원칙 하에 요약 내용을 공개합니다. 출처는 위에 언급되어있듯, 인프런, 스프링과 JPA 기반 웹 애플리케이션 개발입니다.

제가 학습한 소스코드는 https://github.com/n00nietzsche/jakestudy_webapp 에 지속적으로 업로드 됩니다. 매 커밋 메세지에 강의의 어디 부분까지 진행됐는지 기록해놓겠습니다.


관심 주제 테스트

  • 요청 본문에 JSON 데이터를 실어 보내기
        mockMvc.perform(post("/" + SettingsController.ADD_TAGS_MAPPING_PATH)
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(tagForm))
                .with(csrf()))
                .andExpect(status().isOk());
  • 테스트에 트랜잭션 적용하기
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
class SettingsControllerTest {
...

사실 이전에 관심주제에 대한 테스트를 스스로 미리 만들어보아서, 딱히 많은 코드가 바뀌진 않았다.

관심 주제 테스트에서 달라진 테스트 방법

  • contentTypeMediaType.APPLICATION_JSON으로 설정해준다.
  • contentJSON 문자열을 입력해준다.
    • ObjectMapper빈을 이용하면 편리하다.

테스트에서 의문사항

@DisplayName("태그 추가 - 정상 케이스")
    @WithAccount(nickname = "jake")
    @Test
    @Transactional
    public void addTagCorrect() throws Exception{

        TagForm tagForm = new TagForm();
        String tagTitle = "안녕하세요.";
        tagForm.setTagTitle(tagTitle);

        mockMvc.perform(post("/" + SettingsController.ADD_TAGS_MAPPING_PATH)
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(tagForm))
                .with(csrf()))
                .andExpect(status().isOk());

        Optional<Tag> optionalTag = tagRepository.findByTitle(tagTitle);
        assertTrue(optionalTag.isPresent());

        Tag tag = optionalTag.get();
        Account account = accountRepository.findByNickname("jake");
        AccountTag accountAndTag = accountTagRepository.findByAccountAndTag(account, tag);
        assertNotNull(accountAndTag);

        // 이상하게 account.getAccountTags() 에는 생기지 않음... why?
        // Controller 에서는 잘 불러와 지는데?
        // 왜인지 양방향 연결이 잘 안됨.. why? list.add() 직접 해주어야 하나
        // N:M 을 1:N 1:M 처럼 일대다 두개로 풀었을 때는 직접 add 해주어야 하는 것 같음
        List<AccountTag> accountTags = account.getAccountTags();
        for (AccountTag accountTag : accountTags) {
            System.out.println("accountTag = " + accountTag.getTag().getTitle());
        }


    }

나는 N:M을 중간에 외래키 2개를 참조하는 테이블을 하나 두어 1:N과 또 다른 1:N으로 풀었다. 이렇게 풀은 이유는 김영한님의 JPA 강의에서 이렇게 하는 것이 유연성이 더 좋다고 얘기했고, 나는 타당하다고 생각했기 때문이다.

그런데, 1:N과 또 다른 1:N으로 풀었을 때, Account 객체 내부에 @OneToManyArrayList<AccountTag>를 매핑받는 필드인 accountTags 필드가 있다. 이 필드는 이상하게 컨트롤러에서 사용할 때는 자동으로 매핑이 잘 받아지는데, 테스트에서는 잘 안받아진다. 이후 수동으로 account.getAccountTags().add() 내용을 추가하니까 잘 받아진다.

아마, N:M1:N, N:1로 푼 경우에서는 수동으로 해줘야 하는 것 같다. 컨트롤러도 그 당시는 매핑이 잘 받아졌지만 나중에는 또 안받아질 수도 있으니 확실하게 해줘야겠다. 그리고 혹시나해서 중복된 값이 들어가나 싶어 확인해봤는데, 중복된 값이 들어가거나 하는 일은 발생하지 않았다.

Builder 주의점

Builder를 이용하여 객체를 생성하면, 기본 값으로 설정해둔 것들이 적용이 안되는 것 같다.

위와 같이 클래스 정의 내부에서 기본 값을 분명 설정해줬는데.

위와 같이 테스트를 짜서 출력해보면,

빌더에서는 하나도 안들어가있다. 아주 큰 문제다.

앞으로 빌더는 쓰지 않는 것으로...

정리

아무튼 위의 두가지 사실 때문에 많이 헤맸다.

The builder pattern simplifies the creation of objects. 라는데, 전혀 공감되지 않는다. it just increases complexity.

profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글