πŸ–₯️ Web Development Study/Back-End

[Back-End] μŠ€ν”„λ§ μž…λ¬Έ :: νšŒμ› 관리 예제 - λ°±μ—”λ“œ 개발

ibelieveinme 2024. 12. 25. 23:06
728x90

1. νšŒμ› domain κ³Ό repository λ§Œλ“€κΈ°

 

src/main/java/com.yoonsung.firstproject/domain/Member.java

package com.yoonsung.firstproject.domain;

public class Member {

    private Long id;
    private String name;

    public Long getId(){
        return id;
    }
    public void setId(Long id){
        this.id = id;
    }
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
}

 

 

src/main/java/com.yoonsung.firstproject/repository/MemberRepository.java

package com.yoonsung.firstproject.repository;

import com.yoonsung.firstproject.domain.Member;

import java.util.List;
import java.util.Optional;

public interface MemberRepository {
    Member save(Member member);
    Optional<Member> findById(Long id);
    Optional<Member> findByName(String name);
    List<Member> findAll();
}

 

 

src/main/java/com.yoonsung.firstproject/repository/MemoryMemberRepository.java

package com.yoonsung.firstproject.repository;

import com.yoonsung.firstproject.domain.Member;
import java.util.*;

public class MemoryMemberRepository implements MemberRepository{

    private static Map<Long, Member> store = new HashMap<>();
    private static long sequence = 0L;

    @Override
    public Member save(Member member) {
        member.setId(++sequence);
        store.put(member.getId(), member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id)); // null 처리
    }

    @Override
    public Optional<Member> findByName(String name) {
        return store.values().stream()
                .filter(member -> member.getName().equals(name))
                .findAny();
    }

    @Override
    public List<Member> findAll() {
        return new ArrayList<>(store.values());
    }

    public void clearStore(){
        store.clear();
    }
}

 

 

 

2. test code μž‘μ„±

java μ—μ„œλŠ” Junit 으둜 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό ν•œλ°©μ— μž‘μ„± κ°€λŠ₯함.

 

test/java/com.yoonsung.firstproject/repository/MemoryMemberRepositoryTest.java

package com.yoonsung.firstproject.repository;

import com.yoonsung.firstproject.domain.Member;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.util.List;

import static org.assertj.core.api.Assertions.*;

class MemoryMemberRepositoryTest {
    MemoryMemberRepository repository = new MemoryMemberRepository();

    @AfterEach
    public void afterEach(){
        repository.clearStore();
    }

    @Test
    public void save(){
        Member member = new Member();
        member.setName("spring");

        repository.save(member);

        Member result = repository.findById(member.getId()).get();
        assertThat(member).isEqualTo(result);
    }

    @Test
    public void findByName(){
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);

        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);

        Member result = repository.findByName("spring1").get();
        assertThat(result).isEqualTo(member1);
    }

    @Test
    public void findAll(){
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);

        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);

        List<Member> result = repository.findAll();
        assertThat(result.size()).isEqualTo(2);
    }
}

ν•¨μˆ˜ λ‹¨μœ„μ™€ class λ‹¨μœ„λ‘œ Test λ₯Ό μ‹€ν–‰ν•  수 μžˆλ‹€.

 

 

3. test code 확인

Test κ°€ 잘 μˆ˜ν–‰λ˜μ—ˆλŠ”μ§€ ν™•μΈν•˜λŠ” 법은 Assertion 라이브러리λ₯Ό μ΄μš©ν•˜λŠ” 것이닀.

import static org.assertj.core.api.Assertions.*;

//Assertions.assertEquals(member, result);
assertThat(member).isEqualTo(result);

주석뢀뢄 보닀 μ•„λž˜ μ½”λ“œκ°€ 더 κ°€μ‹œμ μ΄μ–΄μ„œ 자주 μ‚¬μš©ν•˜μ‹ λ‹€κ³  ν•˜μ…¨λ‹Ή.

 

assertThat(member).isEqualTo(result); μˆ˜ν–‰ ν™”λ©΄. 정상 μ‹€ν–‰.

 

 

assertThat(member).isEqualTo(null);  μˆ˜ν–‰ ν™”λ©΄. μ—λŸ¬ λ°œμƒ.

 

 

참고둜, class λ‹¨μœ„λ‘œ Test λ₯Ό μ‹€ν–‰ν–ˆμ„ λ•Œ ν•¨μˆ˜μ˜ μˆœμ„œλ₯Ό 보μž₯ν•˜μ§€ λͺ»ν•œλ‹€.

νŠΉμ • ν•¨μˆ˜λ₯Ό λ¨Όμ € μ‹€ν–‰ν•¨μœΌλ‘œμ¨ μ—λŸ¬κ°€ λ°œμƒν•  μˆ˜λ„ μžˆλ‹€.

κ·Έλž˜μ„œ ν•˜λ‚˜μ˜ ν…ŒμŠ€νŠΈ ν›„ 곡용 μ €μž₯곡간을 ν΄λ¦¬μ–΄ν•΄μ€˜μ•Ό ν•œλ‹€.

μ•„λž˜ 두 ν΄λž˜μŠ€μ— 각각 ν•¨μˆ˜λ₯Ό μΆ”κ°€ν•΄μ£Όμž.

 

src/main/java/com.yoonsung.firstproject/repository/MemoryMemberRepository.java

    public void clearStore(){
        store.clear();
    }

 

 

test/java/com.yoonsung.firstproject/repository/MemoryMemberRepositoryTest.java

    @AfterEach
    public void afterEach(){
        repository.clearStore();
    }

 

 

clear μ½”λ“œ μΆ”κ°€ ν›„ μ—λŸ¬ 없이 정상 μ‹€ν–‰λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€.

 

 

4. νšŒμ› μ„œλΉ„μŠ€ 개발

src/main/java/com.yoonsung.firstproject/service/MemberService.java

package com.yoonsung.firstproject.service;

import com.yoonsung.firstproject.domain.Member;
import com.yoonsung.firstproject.repository.MemberRepository;
import com.yoonsung.firstproject.repository.MemoryMemberRepository;

import java.util.List;
import java.util.Optional;

public class MemberService {

    private final MemberRepository memberRepository = new MemoryMemberRepository();

    // νšŒμ›κ°€μž…
    public Long join(Member member){
        validateDuplicateMember(member); // 쀑볡 νšŒμ› 검증
        memberRepository.save(member);
        return member.getId();
    }

    // νŠΉμ • κΈ°λŠ₯을 κ°€μ§€λ―€λ‘œ ν•¨μˆ˜λ‘œ λΉΌκΈ°
    private void validateDuplicateMember(Member member){
//        Optional<Member> result = memberRepository.findByName(member.getName());
//        result.ifPresent(m -> {
//            throw new IllegalStateException("이미 μ‘΄μž¬ν•˜λŠ” νšŒμ›μž…λ‹ˆλ‹€.");
//        });
        memberRepository.findByName(member.getName())
                .ifPresent(m -> {
                    throw new IllegalStateException("이미 μ‘΄μž¬ν•˜λŠ” νšŒμ›μž…λ‹ˆλ‹€.");
                });
    }

    /**
     * 전체 νšŒμ› 쑰회
     */
    public List<Member> findMembers(){
        return memberRepository.findAll();
    }

    /**
     * νšŒμ› ν•œλͺ… 쑰회
     */
    public Optional<Member> findOne(Long memberId){
        return memberRepository.findById(memberId);
    }
}

 

 

* μ°Έκ³ . μ½”λ“œ ν•¨μˆ˜λ‘œ μΆ”μΆœν•˜κΈ°

νŠΉμ • κΈ°λŠ₯을 κ°–λŠ” μ½”λ“œλŠ” ν•¨μˆ˜λ‘œ 빼자.

이 λ•Œ νŽΈν•˜κ²Œ ν•¨μˆ˜λ‘œ μΆ”μΆœν•˜λŠ” 방법이 μžˆλ‹€.

μΆ”μΆœν•˜κ³  싢은 ν•¨μˆ˜λ₯Ό λ“œλž˜κ·Έ ν•˜κ³  Ctrl + T -> Extract -> Method(Ctrl + Alt + M) λ₯Ό ν•˜λ©΄ λœλ‹€.

 

*Ctrl + Alt + V : ν•œλ²ˆμ— 이름 λ°”κΎΈκΈ°.

 

 

5. νšŒμ› μ„œλΉ„μŠ€ μ½”λ“œ Test

 

1) λ‹¨μΆ•ν‚€λ‘œ Test λ₯Ό μœ„ν•œ νŒ¨ν‚€μ§€, μžλ°”νŒŒμΌ λ§Œλ“€κΈ°. class μ—μ„œ Ctrl + Shift + T λˆ„λ₯΄κΈ°.

package com.yoonsung.firstproject.service;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class MemberServiceTest {

    @Test
    void join() {
    }

    @Test
    void findMembers() {
    }

    @Test
    void findOne() {
    }
}

 

 

2) given, when, then 주석 적어두고 νŒ¨ν„΄μ„ λͺ…μ‹œν•΄μ„œ μ½”λ“œλ₯Ό 적어주기. <- Tip!

package com.yoonsung.firstproject.service;

import com.yoonsung.firstproject.domain.Member;
import com.yoonsung.firstproject.repository.MemoryMemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository;

    // 같은 λ©”λͺ¨λ¦¬μ˜ MemoryMemberRepository λ₯Ό μ‚¬μš©ν•  수 있게 λœλ‹€.
    // Dependency Injection
    @BeforeEach
    public void beforeEach(){
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }

    @AfterEach
    public void afterEach(){
        memberRepository.clearStore();
    }

    @Test
    void join() {
        //given μ–΄λ–€ 상황이 μ£Όμ–΄μ‘Œμ„ λ•Œ
        Member member = new Member();
        member.setName("hello");

        //when 이걸 μ‹€ν–‰ν–ˆμ„ λ•Œ
        Long saveId = memberService.join(member);

        //then 이 κ²°κ³Όκ°€ λ‚˜μ™€μ•Ό ν•΄.
        Member findMember = memberService.findOne(saveId).get();
        assertThat(member.getName()).isEqualTo(findMember.getName());
    }

    @Test
    public void ExceptionDuplicateMember(){
        //given
        Member member1 = new Member();
        member1.setName("spring");

        Member member2 = new Member();
        member2.setName("spring");

        //when
        memberService.join(member1);
//        try{
//            memberService.join(member2);
//            fail();
//        } catch(IllegalStateException e){
//            assertThat(e.getMessage()).isEqualTo("이미 μ‘΄μž¬ν•˜λŠ” νšŒμ›μž…λ‹ˆλ‹€.");
//        }
        IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
        assertThat(e.getMessage()).isEqualTo("이미 μ‘΄μž¬ν•˜λŠ” νšŒμ›μž…λ‹ˆλ‹€.");

        //then
    }
    @Test
    void findMembers() {

    }

    @Test
    void findOne() {

    }
}

 

 

* Try Catch λ¬Έ λŒ€μ‹  assertThrows 와 IllegalStateException 을 μ΄μš©ν•˜λŠ” 법.

    @Test
    public void ExceptionDuplicateMember(){
        //given
        Member member1 = new Member();
        member1.setName("spring");

        Member member2 = new Member();
        member2.setName("spring");

        //when
        memberService.join(member1);
//        try{
//            memberService.join(member2);
//            fail();
//        } catch(IllegalStateException e){
//            assertThat(e.getMessage()).isEqualTo("이미 μ‘΄μž¬ν•˜λŠ” νšŒμ›μž…λ‹ˆλ‹€.");
//        }
        IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
        assertThat(e.getMessage()).isEqualTo("이미 μ‘΄μž¬ν•˜λŠ” νšŒμ›μž…λ‹ˆλ‹€.");

        //then
    }

 

 

* Dependency Injection

MemoryMemberRepository λ₯Ό MemberServiceTest 클래슀 μ•ˆμ—μ„œ 또 new 둜 μƒμ„±ν•˜μ§€ μ•Šκ³  μœ„μ—μ„œ μž‘μ„±ν•œ MemoryMemberRepositoryTest ν΄λž˜μŠ€μ—μ„œ μ‚¬μš©ν•œ MemoryMemberRepository 객체λ₯Ό μ‚¬μš©ν•˜λŠ” 법.

public class MemberService {

    private final MemberRepository memberRepository;

    public MemberService(MemberRepository memberRepository){
        this.memberRepository = memberRepository;
    }
class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository;

    // 같은 λ©”λͺ¨λ¦¬μ˜ MemoryMemberRepository λ₯Ό μ‚¬μš©ν•  수 있게 λœλ‹€.
    // Dependency Injection
    @BeforeEach
    public void beforeEach(){
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }
728x90