nonneng.ee
Daeun-rithm
nonneng.ee
์ „์ฒด ๋ฐฉ๋ฌธ์ž
์˜ค๋Š˜
์–ด์ œ
  • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (51)
    • Back-end (17)
      • Server (3)
      • Database (3)
      • Spring (9)
      • Node.js (1)
    • Book (1)
      • ์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ” (0)
      • ๋Œ€๊ทœ๋ชจ ์‹œ์Šคํ…œ ์„ค๊ณ„ (1)
    • Algorithm (1)
      • Greedy, Implementation (6)
      • Dynamic Programming (5)
      • Data Structure (3)
      • Sorting (2)
      • Concept (1)
    • TIL (11)
    • Software (3)
      • Design Pattern (3)
    • Computer Science (1)

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ํ™ˆ
  • ํƒœ๊ทธ
  • ๋ฐฉ๋ช…๋ก

๊ณต์ง€์‚ฌํ•ญ

์ธ๊ธฐ ๊ธ€

ํƒœ๊ทธ

  • DP
  • Spring
  • APM
  • MySQL
  • jwt
  • ํŒŒ์ด์ฌ
  • ์†Œ์Šค์„ค์น˜
  • ์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ”
  • node js
  • ๊ตฌ๋™์›๋ฆฌ
  • ์„œ๋ฒ„
  • ์šฐ๋ถ„ํˆฌ
  • ์•„์ดํ…œ8
  • ๊ฐ€์ƒ๋จธ์‹ 
  • ๋ธŒ๋ฃจํŠธํฌ์Šค
  • Postman
  • ์•„์ดํ…œ6
  • ์•„์ดํ…œ9
  • ๋ฐฑ์ค€
  • ๊ตฌํ˜„
  • ์•„์ดํ…œ 25
  • ์ปดํŒŒ์ผ์„ค์น˜
  • ์•„์ดํ…œ 23
  • API
  • Java
  • ์ž๋ฐ”
  • Restful API
  • ์ˆ˜๋™์„ค์น˜
  • JPA
  • ์—๋Ÿฌ

์ตœ๊ทผ ๋Œ“๊ธ€

์ตœ๊ทผ ๊ธ€

ํ‹ฐ์Šคํ† ๋ฆฌ

hELLO ยท Designed By ์ •์ƒ์šฐ.
nonneng.ee

Daeun-rithm

[Spring] ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ 01 - ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ ์ •๋ฆฌ, domain & repository ์ƒ์„ฑ → Test code ์ž‘์„ฑ
Back-end/Spring

[Spring] ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ 01 - ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ ์ •๋ฆฌ, domain & repository ์ƒ์„ฑ → Test code ์ž‘์„ฑ

2022. 2. 17. 18:01

๐ŸŒณ ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ ์ •๋ฆฌ

๋ฐ์ดํ„ฐ

 : ํšŒ์›ID, ์ด๋ฆ„

๊ธฐ๋Šฅ

 : ํšŒ์› ๋“ฑ๋ก, ํšŒ์› ์กฐํšŒ

DB

 : ์•„์ง ์–ด๋–ค DB๋ฅผ ์‚ฌ์šฉํ• ์ง€ ์ •ํ•ด์ง€์ง€ ์•Š์€ ๊ฐ€์ƒ์˜ ์‹œ๋‚˜๋ฆฌ์˜ค

โ–ช ๋”ฐ๋ผ์„œ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ตฌํ˜„ ํด๋ž˜์Šค๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„

   → ๊ตฌํ˜„์ฒด๋ฅผ ํ†ตํ•ด ๊ฐ€๋ฒผ์šด ๋ฉ”๋ชจ๋ฆฌ ๊ธฐ๋ฐ˜์˜ ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ ์‚ฌ์šฉ

โ–ช ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ → junit

์ผ๋ฐ˜์ ์ธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ณ„์ธต ๊ตฌ์กฐ

โ–ช controller → ์›น MVC์˜ ์ปจํŠธ๋กค๋Ÿฌ ์—ญํ• 

โ–ช service → ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ตฌํ˜„

โ–ช repository → ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ง์ ‘ ์ ‘๊ทผ, ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ฅผ DB์— ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌ

   → Node์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ model๊ณผ ๋น„์Šทํ•œ ์—ญํ• ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋  ๋“ฏ ํ•˜๋‹ค

โ–ช domain → ๋น„์ฆˆ๋‹ˆ์Šค ๋„๋ฉ”์ธ ๊ฐ์ฒด

   → ํšŒ์›, ์ฃผ๋ฌธ ๋“ฑ๋“ฑ ์ฃผ๋กœ DB์— ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌ๋˜์–ด์ง€๋Š” ๊ฐ์ฒด

ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„

๐ŸŒณ ํšŒ์› ๋„๋ฉ”์ธ๊ณผ ๋ ˆํฌ์ง€ํ† ๋ฆฌ

→ ์ผ๋ฐ˜์  ๊ณ„์ธตํ˜• ๊ตฌ์กฐ๋Œ€๋กœ ์ž‘์„ฑ

ํšŒ์› ๋„๋ฉ”์ธ ์ƒ์„ฑ

main/domain/Member

public class Member {
    private Long id;  // ์‹œ์Šคํ…œ์ƒ์—์„œ ์ €์žฅํ•˜๋Š” 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;
    }
}

๋ ˆํฌ์ง€ํ† ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ

main/repository/MemberRepository

public interface MemberRepository {
    Member save(Member member);
    Optional<Member> findById(Long id); // optional๊ธฐ๋Šฅ ๊ณต๋ถ€
    Optional<Member> findByName(String name);
    List<Member> findAll();
}

๋ ˆํฌ์ง€ํ† ๋ฆฌ์— 4๊ฐ€์ง€ ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.

ํšŒ์› ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌํ˜„์ฒด

DB๊ฐ€ ์„ ์ •๋˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ์ผ์‹œ์ ์œผ๋กœ ์ƒ์„ฑํ•œ ํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๊ตฌํ˜„์ฒด

main/repository/MemoryMemberRepository

@Repository
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);   // id setting
        store.put(member.getId(), member);  // store
        return member;
    }

    // id๋กœ ์ฐพ๊ธฐ
    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id));
    }

    // name์œผ๋กœ ์ฐพ๊ธฐ
    @Override
    public Optional<Member> findByName(String name) {
        return store.values().stream()
                .filter(member -> member.getName().equals(name))
                .findAny();
    }

    // ๋ชจ๋‘ ์ฐพ๊ธฐ
    @Override
    public List<Member> findAll() {
        // values <-> members
        return new ArrayList<>(store.values());
    }

    // test์šฉ
    public void clearStore(){
        store.clear();
    }
}

โ–ช hashmap์„ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅ

   → ์‹ค๋ฌด์—์„œ๋Š” ๊ณต์œ ๋˜๋Š” hashmap์„ ์‚ฌ์šฉํ•  ๋•Œ ๋™์‹œ์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด concreteHashmap์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋‹ค

โ–ช Long ํƒ€์ž…์œผ๋กœ ํ‚ค๊ฐ’(pk) ์ƒ์„ฑ

โ–ช Optional.ofNullable

   → ๊ฐ’์ด null์ธ์ง€ ์•„๋‹Œ์ง€ ํ™•์‹ ํ•  ์ˆ˜ ์—†๋Š” ๊ฐ์ฒด๋ฅผ ๋‹ด๊ณ ์žˆ๋Š” Optional๊ฐ์ฒด ์ƒ์„ฑ

   → ๊ฒฐ๊ณผ๊ฐ’์ด null์ผ ์ˆ˜๋„ ์žˆ๋‹ค๋ฉด Optional๋กœ ๊ฐ์‹ธ์ฃผ์–ด ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค

โ–ช List<Member>

   → ์‹ค๋ฌด์—์„œ๋„ List๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋‹ค

๐ŸŒณ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ

โ–ช ์‹ค๋ฌด์—์„œ test code ์—†์ด๋Š” ์ž‘์—…์ด ๋ถˆ๊ฐ€๋Šฅํ•  ์ •๋„๋กœ ์ค‘์š”ํ•˜๋‹ค๊ณ  ํ•œ๋‹คโญ

โ–ช JUnit์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ฉฐ ๋ฒˆ๊ฑฐ๋กœ์›€์„ ์ค„์ธ๋‹ค

โ–ช JUnit : ์ž๋ฐ”์šฉ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ์„ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ

   → ๊ฐ™์€ ํŒจํ‚ค์ง€ ๋‚ด์— ํ…Œ์ŠคํŠธ ๋Œ€์ƒ ํด๋ž˜์Šค์™€ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๊ฐ€ ์œ„์น˜ํ•˜๋„๋ก ์„ค๊ณ„ํ•œ๋‹ค

   → ๋ณดํ†ต ํŒจํ‚ค์ง€, ํด๋ž˜์Šค ์ด๋ฆ„ ๋“ฑ ๋ชจ๋‘ ๊ฐ™๊ฒŒ test์—๋„ ์ž‘์„ฑํ•ด์ค€๋‹ค

   → @Test ์–ด๋…ธํ…Œ์ด์…˜์„ ์„ ์–ธํ•˜์—ฌ ๋ฉ”์†Œ๋“œ๊ฐ€ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ์ž„์„ ์„ ์–ธํ•œ๋‹ค

ํšŒ์› ๋ ˆํฌ์ง€ํ† ๋ฆฌ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค

โ–ช ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ given → when → then ํŒจํ„ด์œผ๋กœ ์ž‘์„ฑํ•˜๋Š”๊ฒƒ์ด ์ข‹๋‹ค.

  given ↔ ์ฃผ์–ด์ง„ ์ƒํ™ฉ์—์„œ

  when ↔ ์ด๊ฒƒ์„ ์‹คํ–‰ํ–ˆ์„ ๋•Œ

  then ↔ ์ด๋Ÿฐ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™€์•ผํ•œ๋‹ค!

 

test/repository/MemoryMemberRepositoryTest

( ↔ main/repository/MemoryMemberRepository ์— ๋Œ€ํ•œ test code)

 

save ํ…Œ์ŠคํŠธ

MemoryMemberRepository repository = new MemoryMemberRepository();

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

        // when
        repository.save(member);

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

โ–ช get()์œผ๋กœ Optional๊ฐ์ฒด๋ฅผ ๊บผ๋‚ด์„œ given member์™€ ๊ฐ™์€์ง€ ๋น„๊ตํ•˜๋Š” ๋ฉ”์†Œ๋“œ

โ–ช assertThat(member).isEqualTo(result)

   → ์š”์ฆ˜ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋กœ, ๋ฐฉํ–ฅ์„ฑ์ด ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค๋Š” ์žฅ์ 

   → .assertEquals(member, result) ๋ฉ”์†Œ๋“œ๋„ ๊ฐ™์€ ๊ธฐ๋Šฅ

 

findByName ํ…Œ์ŠคํŠธ

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

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

        // when
        Member result = repository.findByName("spring1").get();

        // then
        assertThat(result).isEqualTo(member1);
    }

given ↔ spring1, spring2๋ผ๋Š” ํšŒ์›์ด ๊ฐ€์ž…๋œ ์ƒํ™ฉ

when ↔ “spring1” ๊ฐ์ฒด๋ฅผ ๊บผ๋ƒˆ์„ ๋•Œ (์žˆ๋Š”์ง€ ์—†๋Š”์ง€ ๋ชจ๋ฅด๋‹ˆ๊นŒ Optional ๊ฐ์ฒด)

then ↔ isEqualTo() ๋กœ ๋น„๊ต

 

findAll ํ…Œ์ŠคํŠธ

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

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

        // when
        List<Member> result = repository.findAll();

        // then
        assertThat(result.size()).isEqualTo(2);
    }**

โ–ช ๊ฐ์ฒด 2๊ฐœ ๋ชจ๋‘ ์ž˜ ์ €์žฅ๋˜์—ˆ๋‚˜ ํ™•์ธํ•˜๋Š” ๋ฉ”์†Œ๋“œ

 

์ด์ œ ํ…Œ์ŠคํŠธ ํ•ด๋ณด์ž

๊ทธ๋Ÿฐ๋ฐ

ํ…Œ์ŠคํŠธ๊ฐ€ findAll → findByName ์ˆœ์„œ๋กœ ์‹คํ–‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•œ ์—๋Ÿฌ์ด๋‹ค.

(findAll() ์‹คํ–‰๋˜๋ฉด์„œ ์ด๋ฏธ spring1, spring2 ๊ฐ์ฒด๊ฐ€ ์ €์žฅ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— findByName์—์„œ ๋ฌธ์ œ ๋ฐœ์ƒ)

โ–ช ๋ฉ”์†Œ๋“œ๋Š” ์ˆœ์„œ๋Œ€๋กœ ๋Œ์•„๊ฐ€์ง€ ์•Š๋Š”๋‹ค,, ์•Œ์•„์„œ ๋Œ์•„๊ฐ€๊ธฐ ๋•Œ๋ฌธ์—

   → ์ˆœ์„œ ์˜์กด์ ์œผ๋กœ ์„ค๊ณ„ํ•˜๋ฉด ์ ˆ๋Œ€ ์•ˆ๋œ๋‹ค!

โ–ช ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํ…Œ์ŠคํŠธ๋ฅผ ํ•œ ๋ฒˆ ๋Œ๋ฆด ๋•Œ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ฆฌ์–ด ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

 

@AfterEach๋ฅผ ํ†ตํ•œ ์ฝœ๋ฐฑํ•จ์ˆ˜

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

๊ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๋งˆ๋‹ค ์ด์ „์˜ ํ…Œ์ŠคํŠธ์— ์˜ํ•ด ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋“ค์„ ์‚ญ์ œํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

โ–ช test ํด๋ž˜์Šค๋ถ€ํ„ฐ ๋งŒ๋“ค๊ณ  ๋‚˜์„œ repository๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ TDD๋ผ๊ณ  ํ•œ๋‹ค.

โ–ช ํŠนํžˆ ์—ฌ๋Ÿฌ๋ช…์ด์„œ ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” testcode๊ฐ€ ํ•„์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๊นŠ์ด์žˆ๊ฒŒ ๊ณต๋ถ€ํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

 

 

์ž๋ฃŒ ์ถœ์ฒ˜

์ธํ”„๋Ÿฐ - ์Šคํ”„๋ง ์ž…๋ฌธ ์ฝ”๋“œ๋กœ ๋ฐฐ์šฐ๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ, ์›น MVC, DB ์ ‘๊ทผ ๊ธฐ์ˆ  (๊น€์˜ํ•œ)

 

'Back-end > Spring' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Spring] ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ 02 - ํšŒ์› ์„œ๋น„์Šค ๊ฐœ๋ฐœ โ†’ Test Code ์ž‘์„ฑ  (0) 2022.02.19
[Spring] ์ •์  ์ปจํ…์ธ , MVC์™€ ํ…œํ”Œ๋ฆฟ ์—”์ง„, API  (0) 2022.02.16
[Spring] ํ™˜๊ฒฝ ๊ตฌ์ถ•, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, thymeleaf ํ…œํ”Œ๋ฆฟ ์—”์ง„ ๋™์ž‘ ์›๋ฆฌ  (0) 2022.02.15
    'Back-end/Spring' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
    • [Spring] ์Šคํ”„๋ง Bean๊ณผ ์˜์กด๊ด€๊ณ„ - ์ปดํฌ๋„ŒํŠธ ์Šค์บ” & ์ž๋™ ์˜์กด๊ด€๊ณ„ vs ์Šคํ”„๋ง Bean ์ง์ ‘ ๋“ฑ๋ก
    • [Spring] ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ 02 - ํšŒ์› ์„œ๋น„์Šค ๊ฐœ๋ฐœ → Test Code ์ž‘์„ฑ
    • [Spring] ์ •์  ์ปจํ…์ธ , MVC์™€ ํ…œํ”Œ๋ฆฟ ์—”์ง„, API
    • [Spring] ํ™˜๊ฒฝ ๊ตฌ์ถ•, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, thymeleaf ํ…œํ”Œ๋ฆฟ ์—”์ง„ ๋™์ž‘ ์›๋ฆฌ
    nonneng.ee
    nonneng.ee

    ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”