๐Ÿ“š Computer Science/Server

[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