์ฌ์ค ์ด๋ป๊ฒ ์งํํด์ผ ํ ์ง ๊ณ ๋ฏผ์ ์กฐ๊ธ ํ์ต๋๋ค.
๋ก๊ทธ์ธ์ ๋จผ์ ํ๋๊ฒ ๋ง๋๊ฑด์ง, ๊ธฐ๋ฅ ๊ตฌํ์ด ๋จผ์ ์ผ์ง...
๊ทธ๋ฐ๋ฐ ์ต๊ทผ์ ์ํ๋ฆฌํฐ๋ฅผ ๊ณต๋ถํ๊ธฐ๋ ํ๊ณ , JWT ๊ด๋ จํด์ ๊ณต๋ถ๋ฅผ ์กฐ๊ธ ํด๋ณด๊ณ ์ถ์ ๋ง์์ด ์ปค์ (+ ์ถ๊ฐ๋ก ์ ๊ฐ ์ฐธ๊ณ ํ๋ ๋ธ๋ก๊ทธ์์๋ ๋ก๊ทธ์ธ์ ๋จผ์ ํ๋๋ผ๊ตฌ์) ๋ก๊ทธ์ธ ๋ถํฐ ๋ง๋ค๋๋ก ํ๊ฒ ์ต๋๋ค.
์ฐ์ ์ํฐํฐ๋ ํ์ ์ํฐํฐ์์ ๋ก๊ทธ์ธ์ ํ์ํ ๊ธฐ๋ณธ์ ์ธ ์ ๋ณด๋ง ๊ฐ์ง๊ณ ์์ฑํ๋๋ก ํ๊ฒ ์ต๋๋ค.
๋ก๊ทธ์ธ์ด ๋๋ ์ดํ, ์ ์ฒด์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ์๊ตฌ์ฌํญ์ ๋ถ์ํ์ฌ ๋๋ฉ์ธ์ ์ค๊ณ ํ ์ํฐํฐ๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ผ๋ก ์งํํ๊ฒ ์ต๋๋ค.
- ์ํ๋ฆฌํฐ๋ฅผ ์ด์ฉํ JSON ๋ฐ์ดํฐ๋ก ๋ก๊ทธ์ธ (์งํ ์ค)
- JWT๋ฅผ ์ด์ฉํ ์ธ์ฆ
- ๋๋ฉ์ธ, ํ ์ด๋ธ ์ค๊ณ, ์ํฐํฐ ์์ฑ
- ๋๊ธ ์ญ์ ๋ก์ง ๊ตฌํ
- ํ์๊ฐ์ + ์ ๋ณด์์ ๋ฑ ํ์ ์๋น์ค ๊ตฌํ
- ๊ฒ์ํ ์๋น์ค ๊ตฌํ
- ๋๊ธ ์๋น์ค ๊ตฌํ (1๋๊ธ -> *(๋ฌดํ) ๋๋๊ธ ๊ตฌ์กฐ)
- ์์ธ ์ฒ๋ฆฌ
- ์์ธ ๋ฉ์ธ์ง ๊ตญ์ ํ
- ์นดํ ๊ณ ๋ฆฌ๋ณ ๊ฒ์ํ ๋ถ๋ฅ
- ๊ฒ์๊ธ ํ์ด์ง
- ๋์ ์ธ ๊ฒ์ ์กฐ๊ฑด์ ์ฌ์ฉํ ๊ฒ์
- ์ฌ์ฉ์ ๊ฐ ์ชฝ์ง ๊ธฐ๋ฅ
- ๋ฌดํ ์ชฝ์ง ์คํฌ๋กค
- ๊ฒ์๋ฌผ & ๋๊ธ์ ๋ํ ์๋
- ์ชฝ์ง์ ๋ํ ์๋
- ์ ์ํ ์ฌ์ฉ์ ๊ฐ ์ค์๊ฐ ์ฑํ
- ํ์๊ฐ์ ์ ๊ฒ์ฆ(์: XX๋ํ๊ต XX๊ณผ๊ฐ ์๋๋ฉด ๊ฐ์ ํ ์ ์๊ฒ)
- Swagger๋ฅผ ์ฌ์ฉํ API ๋ฌธ์ ๋ง๋ค๊ธฐ
- ์ ๊ณ & ๋ธ๋๋ฆฌ์คํธ ๊ธฐ๋ฅ
- AOP๋ฅผ ํตํ ๋ก๊ทธ
- ์ด๋๋ฏผ ํ์ด์ง
- ์บ์
- ๋ฐฐํฌ (+ ๋ฌด์ค๋จ ๋ฐฐํฌ)
- ๋ฐฐํฌ ์๋ํ
- ํฌํธ์ ์ด๋ํฐ ์ค๊ณ๋ฅผ ๋ฐ๋ฅด๋ ํจํค์ง ๊ตฌ์กฐ ์ค๊ณํ๊ธฐ
- ...
ํ์๊ฐ์ & ๋ก๊ทธ์ธ ์๊ตฌ์ฌํญ ๋ถ์
- ์์ด๋์ ๋น๋ฐ๋ฒํธ, ์ด๋ฆ, ๋๋ค์(๋ณ๋ช ), ๋์ด๋ฅผ ์ ๋ ฅ๋ฐ์ต๋๋ค.
- ์์ด๋๋ ์ค๋ณต๋ ์ ์์ต๋๋ค.
- ๋น๋ฐ๋ฒํธ์ ์ด๋ฆ, ๋๋ค์๊ณผ ๋์ด๋ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
- ๋น๋ฐ๋ฒํธ๋ ์ํธํ๋์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋ฉ๋๋ค.
- ํ์์ ํฌํจํ ๋ชจ๋ ์ํฐํฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋ ๋, ๋ฑ๋ก ์๊ฐ๊ณผ ์ ๋ฐ์ดํธ ์๊ฐ์ ๋ฑ๋กํ๋๋ก ํ๊ฒ ์ต๋๋ค.
- ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด JWT๋ฅผ ๋ฐ๊ธํด์ฃผ๋ฉฐ, ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ ์ฐ๋ฆฌ์ ๊ฒ์ํ ์๋น์ค API๋ฅผ ์ด์ฉํ ์ ์์ต๋๋ค.
- ํ์๊ฐ์ ์ผ๋ก๋ USER ๊ถํ์ ํ์๋ง ๊ฐ์ ํ ์ ์์ต๋๋ค. ADMIN ๊ถํ์ ์ง์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๋ ฅํ์ฌ ์ง์ ํด์ฃผ๋๋ก ํ๊ฒ ์ต๋๋ค.
ํ์ ์ํฐํฐ ์์ฑ
ํจํค์ง๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
@Table(name = "MEMBER")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@AllArgsConstructor
@Builder
public class Member {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private Long id; //primary Key
@Column(nullable = false, length = 30, unique = true)
private String username;//์์ด๋
private String password;//๋น๋ฐ๋ฒํธ
@Column(nullable = false, length = 30)
private String name;//์ด๋ฆ(์ค๋ช
)
@Column(nullable = false, length = 30)
private String nickName;//๋ณ๋ช
@Column(nullable = false, length = 30)
private Integer age;//๋์ด
@Enumerated(EnumType.STRING)
private Role role;//๊ถํ -> USER, ADMIN
//== ์ ๋ณด ์์ ==//
public void updatePassword(PasswordEncoder passwordEncoder, String password){
this.password = passwordEncoder.encode(password);
}
public void updateName(String name){
this.name = name;
}
public void updateNickName(String nickName){
this.nickName = nickName;
}
public void updateAge(int age){
this.age = age;
}
//== ํจ์ค์๋ ์ํธํ ==//
public void encodePassword(PasswordEncoder passwordEncoder){
this.password = passwordEncoder.encode(password);
}
}
public enum Role {
USER, ADMIN
}
์๋ฅผ ํตํด ๋ค์ ์๊ตฌ์ฌํญ์ ๋ง์กฑ์์ผฐ์ต๋๋ค.
- ์์ด๋์ ๋น๋ฐ๋ฒํธ, ์ด๋ฆ, ๋๋ค์(๋ณ๋ช ), ๋์ด๋ฅผ ์ ๋ ฅ๋ฐ์ต๋๋ค.
- ์์ด๋๋ ์ค๋ณต๋ ์ ์์ต๋๋ค.
- ๋น๋ฐ๋ฒํธ์ ์ด๋ฆ, ๋๋ค์๊ณผ ๋์ด๋ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
- ๋น๋ฐ๋ฒํธ๋ ์ํธํ๋์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋ฉ๋๋ค.
- ํ์์ ํฌํจํ ๋ชจ๋ ์ํฐํฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋ ๋, ๋ฑ๋ก ์๊ฐ๊ณผ ์ ๋ฐ์ดํธ ์๊ฐ์ ๋ฑ๋กํ๋๋ก ํ๊ฒ ์ต๋๋ค.
- ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด JWT๋ฅผ ๋ฐ๊ธํด์ฃผ๋ฉฐ, ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ ์ฐ๋ฆฌ์ ๊ฒ์ํ ์๋น์ค API๋ฅผ ์ด์ฉํ ์ ์์ต๋๋ค.
- ํ์๊ฐ์ ์ผ๋ก๋ USER ๊ถํ์ ํ์๋ง ๊ฐ์ ํ ์ ์์ต๋๋ค. ADMIN ๊ถํ์ ์ง์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๋ ฅํ์ฌ ์ง์ ํด์ฃผ๋๋ก ํ๊ฒ ์ต๋๋ค.
์ด์ 'ํ์์ ํฌํจํ ๋ชจ๋ ์ํฐํฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋ ๋, ๋ฑ๋ก ์๊ฐ๊ณผ ์ ๋ฐ์ดํธ ์๊ฐ์ ๋ฑ๋กํ๋๋ก ํ๊ฒ ์ต๋๋ค.' ๋ผ๋ ์๊ตฌ์ฌํญ์ ๋ง์กฑ์์ผ๋ณด๊ฒ ์ต๋๋ค.
์์ฑ์๊ฐ๊ณผ ์์ ์๊ฐ ๋ฑ๋ก
JPA์ Auditing์ ์ฌ์ฉํ์ฌ ๊ตฌํํ๋๋ก ํ๊ฒ ์ต๋๋ค.
์์ฑ์๊ฐ๊ณผ ์์ ์๊ฐ์ ๋ชจ๋ ์ํฐํฐ์์ ์ฌ์ฉํ ๊ฒ์ด๋ฏ๋ก @MappedSupperclass๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ์ํฐํฐ๊ฐ ์์๋ฐ์ ์ ์๋๋ก ๋ง๋ค์ด์ฃผ๊ฒ ์ต๋๋ค.
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public abstract class BaseTimeEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
@Column(updatable = true)
private LocalDateTime lastModifiedDate;
}
Auditing์ ์ฌ์ฉํ์๋ฉด @EnableAuditing์ ๊ผญ ์คํ๋ง ๋ถํธ ์ค์ ํด๋์ค์ ์ ์ฉํด์ผ ํฉ๋๋ค.
@EnableJpaAuditing
@SpringBootApplication
public class MyboardApplication {
public static void main(String[] args) {
SpringApplication.run(MyboardApplication.class, args);
}
}
Auditing์ด ๋ฌด์์ธ์ง ๋ชจ๋ฅด์๊ฒ ๋ค๋ฉด ๋ค์ ๊ธ์ ์ฐธ๊ณ ๋ฐ๋๋๋ค.
[Spring Data JPA] Auditing
Auditing ์ํฐํฐ๋ฅผ ์์ฑ, ๋ณ๊ฒฝํ ๋์ ์๊ฐ๊ณผ, ๋ณ๊ฒฝํ ์ฌ๋์ ์ถ์ ํ๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น? ์์ํ๊ฒ JPA๋ง ์ด๋ค๋ฉด @PrePersist ๋ฑ์ ๋ฆฌ์ค๋๋ฅผ ๋ฑ๋กํด์ ๋ฑ๋ก๋๋ ์์ ์ ์๊ฐ๊ณผ ์ฌ๋ ๋ฑ์ ์ ์ฅํ
ttl-blog.tistory.com
์ด์ ์ด๋ฅผ Member์ ์ ์ฉ์์ผ ์ฃผ๊ฒ ์ต๋๋ค.
public class Member extends BaseTimeEntity {
์ง๊ธ๊น์ง ์์ฑํ ํจํค์ง ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
MemberRepository ์์ฑ
์ด์ Member ์ํฐํฐ๋ฅผ DB์ ์ฐ๋ํ์ฌ ์ ์ฅ, ์กฐํ ๋ฑ์ ์ญํ ์ ์ํํ๋ MemberRepository ์ธํฐํ์ด์ค๋ฅผ ์์ฑํ๊ฒ ์ต๋๋ค.
ํจํค์ง๋ ๋ค์์ ์์น์ ์์ฑํฉ๋๋ค.
์ฐธ๊ณ ๋ก ์ ๋ ํจํค์ง ๊ตฌ์กฐ๋ฅผ ์๋ ์ฌ์ดํธ๋ฅผ ์ฐธ๊ณ ํ์ฌ ์์ฑํ์์ต๋๋ค.
ํจํค์ง ๊ตฌ์กฐ๋ ์ด๋ป๊ฒ ์ง๋ ๊ฒ ๋ง์๊น?
๊ฐ์ธ ํ๋ก์ ํธ์ธ [๊ผฌ๋ฆฌ๋ณ] ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ์๊ธฐ๋ ์ค๋ฅ์ ๊ฐ๋ฐํ๋ฉด์ ๋๋ ์ ์ ๊ธฐ๋กํ๋ ๊ณณ
velog.io
์ด์ MemberRepository๋ฅผ ์์ฑํ๊ฒ ์ต๋๋ค.
public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByUsername(String username);
boolean existsByUsername(String username);
}
JpaRepository๋ฅผ ์์๋ฐ์์ต๋๋ค.
์ด์ Repository๋ฅผ ํ์ฉํ ํ ์คํธ์ฝ๋๋ฅผ ์์ฑํด๋ณด๊ฒ ์ต๋๋ค.
ํ ์คํธ์ฝ๋ ์์ฑ
๋จ์ถํค๊ฐ ์๋ํ์ง ์๋๋ค๋ฉด ์์ ์์น์ ํ ์คํธ์ฝ๋๋ฅผ ์์ฑํด์ฃผ์ธ์.
ํ ์คํธํด์ผ ํ ๊ธฐ๋ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ํ์ ์ ์ฅ
- ํ์ ์ ์ฅ์ ์์ด๋๊ฐ ์์ผ๋ฉด ์ค๋ฅ
- ํ์ ์ ์ฅ์ ์ด๋ฆ์ด ์์ผ๋ฉด ์ค๋ฅ
- ํ์ ์ ์ฅ์ ๋๋ค์์ด ์์ผ๋ฉด ์ค๋ฅ
- ํ์ ์ ์ฅ์ ๋์ด๊ฐ ์์ผ๋ฉด ์ค๋ฅ
- ํ์ ์ ์ฅ์ ์ค๋ณต๋ ์์ด๋๊ฐ ์์ผ๋ฉด ์ค๋ฅ
- ํ์ ์์
- ํ์ ์ญ์
- existsByUsername์ด ์ ์๋ํ๋์ง
- username์ผ๋ก ํ์ ์ฐพ๊ธฐ ๊ธฐ๋ฅ์ด ์ ์๋ํ๋์ง
- ๊ฐ์ ์ ์์ฑ์๊ฐ์ด ์ ๋ฑ๋ก๋์๋์ง
(ํ์ ๊ฐ์ ์ ๊ถํ์ USER๋ก ์ค์ ํ๋ ๋ถ๋ถ์ ์ดํ Service ๋ก์ง์์ ์งํํ๊ฒ ์ต๋๋ค.)
์ด์ ์ฝ๋๋ฅผ ์์ฑํด๋ณด๊ฒ ์ต๋๋ค.
๊ธฐ๋ณธ์ ์ธ ํ ์คํธ์ฝ๋์ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
import boardexample.myboard.domain.member.Member;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import java.util.Optional;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
@Transactional
class MemberRepositoryTest {
@Autowired MemberRepository memberRepository;
@Autowired EntityManager em;
@AfterEach
private void after(){
em.clear();
}
}
์ด์ ํ ์คํธ๋ฅผ ํ๋์ฉ ์์ฑํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
ํ์์ ์ฅ ์ฑ๊ณต
@Test
public void ํ์์ ์ฅ_์ฑ๊ณต() throws Exception {
//given
Member member = Member.builder().username("username").password("1234567890").name("Member1").nickName("NickName1").role(Role.USER).age(22).build();
//when
Member saveMember = memberRepository.save(member);
//then
Member findMember = memberRepository.findById(saveMember.getId()).orElseThrow(() -> new RuntimeException("์ ์ฅ๋ ํ์์ด ์์ต๋๋ค"));//์์ง ์์ธ ํด๋์ค๋ฅผ ๋ง๋ค์ง ์์๊ธฐ์ RuntimeException์ผ๋ก ์ฒ๋ฆฌํ๊ฒ ์ต๋๋ค.
assertThat(findMember).isSameAs(saveMember);
assertThat(findMember).isSameAs(member);
}
์์ด๋ ์์ด ํ์๊ฐ์ ์ ์ค๋ฅ
@Test
public void ์ค๋ฅ_ํ์๊ฐ์
์_์์ด๋๊ฐ_์์() throws Exception {
//given
Member member = Member.builder().password("1234567890").name("Member1").nickName("NickName1").role(Role.USER).age(22).build();
//when, then
assertThrows(Exception.class, () -> memberRepository.save(member));
}
์ด๋ฆ ์์ด ํ์๊ฐ์ ์ ์ค๋ฅ
@Test
public void ์ค๋ฅ_ํ์๊ฐ์
์_์ด๋ฆ์ด_์์() throws Exception {
//given
Member member = Member.builder().username("username").password("1234567890").nickName("NickName1").role(Role.USER).age(22).build();
//when, then
assertThrows(Exception.class, () -> memberRepository.save(member));
}
๋๋ค์ ์์ด ํ์๊ฐ์ ์ ์ค๋ฅ
@Test
public void ์ค๋ฅ_ํ์๊ฐ์
์_๋๋ค์์ด_์์() throws Exception {
//given
Member member = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).age(22).build();
//when, then
assertThrows(Exception.class, () -> memberRepository.save(member));
}
๋์ด๊ฐ ์์ด ํ์๊ฐ์ ์ ์ค๋ฅ
@Test
public void ์ค๋ฅ_ํ์๊ฐ์
์_๋์ด๊ฐ_์์() throws Exception {
//given
Member member = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").build();
//when, then
assertThrows(Exception.class, () -> memberRepository.save(member));
}
ํ์๊ฐ์ ์ ์ค๋ณต๋ ์์ด๋๊ฐ ์์ผ๋ฉด ์ค๋ฅ
@Test
public void ์ค๋ฅ_ํ์๊ฐ์
์_์ค๋ณต๋_์์ด๋๊ฐ_์์() throws Exception {
//given
Member member1 = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
Member member2 = Member.builder().username("username").password("1111111111").name("Member2").role(Role.USER).nickName("NickName2").age(22).build();
memberRepository.save(member1);
clear();
//when, then
assertThrows(Exception.class, () -> memberRepository.save(member2));
}
ํ์์์
@Test
public void ์ฑ๊ณต_ํ์์์ () throws Exception {
//given
Member member1 = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
memberRepository.save(member1);
clear();
String updatePassword = "updatePassword";
String updateName = "updateName";
String updateNickName = "updateNickName";
int updateAge = 33;
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//when
Member findMember = memberRepository.findById(member1.getId()).orElseThrow(() -> new Exception());
findMember.updateAge(updateAge);
findMember.updateName(updateName);
findMember.updateNickName(updateNickName);
findMember.updatePassword(passwordEncoder,updatePassword);
em.flush();
//then
Member findUpdateMember = memberRepository.findById(findMember.getId()).orElseThrow(() -> new Exception());
assertThat(findUpdateMember).isSameAs(findMember);
assertThat(passwordEncoder.matches(updatePassword, findUpdateMember.getPassword())).isTrue();
assertThat(findUpdateMember.getName()).isEqualTo(updateName);
assertThat(findUpdateMember.getName()).isNotEqualTo(member1.getName());
}
ํ์์ญ์
@Test
public void ์ฑ๊ณต_ํ์์ญ์ () throws Exception {
//given
Member member1 = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
memberRepository.save(member1);
clear();
//when
memberRepository.delete(member1);
clear();
//then
assertThrows(Exception.class, () -> memberRepository.findById(member1.getId()).orElseThrow(() -> new Exception()));
}
existByUsername ์ ์์๋ ํ ์คํธ
@Test
public void existByUsername_์ ์์๋() throws Exception {
//given
String username = "username";
Member member1 = Member.builder().username(username).password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
memberRepository.save(member1);
clear();
//when, then
assertThat(memberRepository.existsByUsername(username)).isTrue();
assertThat(memberRepository.existsByUsername(username+"123")).isFalse();
}
findByUsername ์ ์์๋ ํ ์คํธ
@Test
public void findByUsername_์ ์์๋() throws Exception {
//given
String username = "username";
Member member1 = Member.builder().username(username).password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
memberRepository.save(member1);
clear();
//when, then
assertThat(memberRepository.findByUsername(username).get().getUsername()).isEqualTo(member1.getUsername());
assertThat(memberRepository.findByUsername(username).get().getName()).isEqualTo(member1.getName());
assertThat(memberRepository.findByUsername(username).get().getId()).isEqualTo(member1.getId());
assertThrows(Exception.class,
() -> memberRepository.findByUsername(username+"123")
.orElseThrow(() -> new Exception()));
}
ํ์๊ฐ์ ์ ์์ฑ์๊ฐ ๋ฑ๋ก
@Test
public void ํ์๊ฐ์
์_์์ฑ์๊ฐ_๋ฑ๋ก() throws Exception {
//given
Member member1 = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
memberRepository.save(member1);
clear();
//when
Member findMember = memberRepository.findById(member1.getId()).orElseThrow(() -> new Exception());
//then
assertThat(findMember.getCreatedDate()).isNotNull();
assertThat(findMember.getLastModifiedDate()).isNotNull();
}
์ด๋ ๊ฒ ํ ์คํธ๋ฅผ ๋ชจ๋ ๋๋ด๋ณด์์ต๋๋ค.
ํ ์คํธ์ ์ ์ฒด ์ฝ๋๋ ์๋์ ๊ฐ์ต๋๋ค.
package boardexample.myboard.domain.member.repository;
import boardexample.myboard.domain.member.Member;
import boardexample.myboard.domain.member.Role;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import java.util.Optional;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
@Transactional
class MemberRepositoryTest {
@Autowired MemberRepository memberRepository;
@Autowired EntityManager em;
private void clear(){
em.flush();
em.clear();
}
@AfterEach
private void after(){
em.clear();
}
@Test
public void ํ์์ ์ฅ_์ฑ๊ณต() throws Exception {
//given
Member member = Member.builder().username("username").password("1234567890").name("Member1").nickName("NickName1").role(Role.USER).age(22).build();
//when
Member saveMember = memberRepository.save(member);
//then
Member findMember = memberRepository.findById(saveMember.getId()).orElseThrow(() -> new RuntimeException("์ ์ฅ๋ ํ์์ด ์์ต๋๋ค"));//์์ง ์์ธ ํด๋์ค๋ฅผ ๋ง๋ค์ง ์์๊ธฐ์ RuntimeException์ผ๋ก ์ฒ๋ฆฌํ๊ฒ ์ต๋๋ค.
assertThat(findMember).isSameAs(saveMember);
assertThat(findMember).isSameAs(member);
}
@Test
public void ์ค๋ฅ_ํ์๊ฐ์
์_์์ด๋๊ฐ_์์() throws Exception {
//given
Member member = Member.builder().password("1234567890").name("Member1").nickName("NickName1").role(Role.USER).age(22).build();
//when, then
assertThrows(Exception.class, () -> memberRepository.save(member));
}
@Test
public void ์ค๋ฅ_ํ์๊ฐ์
์_์ด๋ฆ์ด_์์() throws Exception {
//given
Member member = Member.builder().username("username").password("1234567890").nickName("NickName1").role(Role.USER).age(22).build();
//when, then
assertThrows(Exception.class, () -> memberRepository.save(member));
}
@Test
public void ์ค๋ฅ_ํ์๊ฐ์
์_๋๋ค์์ด_์์() throws Exception {
//given
Member member = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).age(22).build();
//when, then
assertThrows(Exception.class, () -> memberRepository.save(member));
}
@Test
public void ์ค๋ฅ_ํ์๊ฐ์
์_๋์ด๊ฐ_์์() throws Exception {
//given
Member member = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").build();
//when, then
assertThrows(Exception.class, () -> memberRepository.save(member));
}
@Test
public void ์ค๋ฅ_ํ์๊ฐ์
์_์ค๋ณต๋_์์ด๋๊ฐ_์์() throws Exception {
//given
Member member1 = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
Member member2 = Member.builder().username("username").password("1111111111").name("Member2").role(Role.USER).nickName("NickName2").age(22).build();
memberRepository.save(member1);
clear();
//when, then
assertThrows(Exception.class, () -> memberRepository.save(member2));
}
@Test
public void ์ฑ๊ณต_ํ์์์ () throws Exception {
//given
Member member1 = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
memberRepository.save(member1);
clear();
String updatePassword = "updatePassword";
String updateName = "updateName";
String updateNickName = "updateNickName";
int updateAge = 33;
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//when
Member findMember = memberRepository.findById(member1.getId()).orElseThrow(() -> new Exception());
findMember.updateAge(updateAge);
findMember.updateName(updateName);
findMember.updateNickName(updateNickName);
findMember.updatePassword(passwordEncoder,updatePassword);
em.flush();
//then
Member findUpdateMember = memberRepository.findById(findMember.getId()).orElseThrow(() -> new Exception());
assertThat(findUpdateMember).isSameAs(findMember);
assertThat(passwordEncoder.matches(updatePassword, findUpdateMember.getPassword())).isTrue();
assertThat(findUpdateMember.getName()).isEqualTo(updateName);
assertThat(findUpdateMember.getName()).isNotEqualTo(member1.getName());
}
@Test
public void ์ฑ๊ณต_ํ์์ญ์ () throws Exception {
//given
Member member1 = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
memberRepository.save(member1);
clear();
//when
memberRepository.delete(member1);
clear();
//then
assertThrows(Exception.class,
() -> memberRepository.findById(member1.getId())
.orElseThrow(() -> new Exception()));
}
@Test
public void existByUsername_์ ์์๋() throws Exception {
//given
String username = "username";
Member member1 = Member.builder().username(username).password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
memberRepository.save(member1);
clear();
//when, then
assertThat(memberRepository.existsByUsername(username)).isTrue();
assertThat(memberRepository.existsByUsername(username+"123")).isFalse();
}
@Test
public void findByUsername_์ ์์๋() throws Exception {
//given
String username = "username";
Member member1 = Member.builder().username(username).password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
memberRepository.save(member1);
clear();
//when, then
assertThat(memberRepository.findByUsername(username).get().getUsername()).isEqualTo(member1.getUsername());
assertThat(memberRepository.findByUsername(username).get().getName()).isEqualTo(member1.getName());
assertThat(memberRepository.findByUsername(username).get().getId()).isEqualTo(member1.getId());
assertThrows(Exception.class,
() -> memberRepository.findByUsername(username+"123")
.orElseThrow(() -> new Exception()));
}
@Test
public void ํ์๊ฐ์
์_์์ฑ์๊ฐ_๋ฑ๋ก() throws Exception {
//given
Member member1 = Member.builder().username("username").password("1234567890").name("Member1").role(Role.USER).nickName("NickName1").age(22).build();
memberRepository.save(member1);
clear();
//when
Member findMember = memberRepository.findById(member1.getId()).orElseThrow(() -> new Exception());
//then
assertThat(findMember.getCreatedDate()).isNotNull();
assertThat(findMember.getLastModifiedDate()).isNotNull();
}
}
๋ค์์๋ ํ์๊ฐ์ ๊ณผ ๋ก๊ทธ์ธ์ ์งํํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ ์ฒด ์ฝ๋๋ ๊นํ๋ธ์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
https://github.com/ShinDongHun1/SpringBoot-Board-API
GitHub - ShinDongHun1/SpringBoot-Board-API
Contribute to ShinDongHun1/SpringBoot-Board-API development by creating an account on GitHub.
github.com
๐ Reference
ํจํค์ง ๊ตฌ์กฐ ์ฐธ๊ณ
ํจํค์ง ๊ตฌ์กฐ๋ ์ด๋ป๊ฒ ์ง๋ ๊ฒ ๋ง์๊น?
๊ฐ์ธ ํ๋ก์ ํธ์ธ [๊ผฌ๋ฆฌ๋ณ] ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ์๊ธฐ๋ ์ค๋ฅ์ ๊ฐ๋ฐํ๋ฉด์ ๋๋ ์ ์ ๊ธฐ๋กํ๋ ๊ณณ
velog.io
์ง์ ๊ฐ๋ฅํ ์ํํธ์จ์ด ์ค๊ณ ํจํด: ํฌํธ์ ์ด๋ํฐ ์ํคํ ์ฒ ์ ์ฉํ๊ธฐ - LINE ENGINEERING
์ก๊ฐํ ์ค๊ณ(Hexagonal Architecture)๋ก ๋ ์ ์๋ ค์ ธ ์๋ ํฌํธ์ ์ด๋ํฐ ์ค๊ณ(Ports and Adapters Architecture)๋, ์ธํฐํ์ด์ค๋ ๊ธฐ๋ฐ ์์(infrastructure)์ ๋ณ๊ฒฝ์ ์ํฅ์ ๋ฐ์ง ์๋ ํต์ฌ ์ฝ๋๋ฅผ ๋ง๋ค๊ณ ์ด๋ฅผ ๊ฒฌ
engineering.linecorp.com
๊ฒ์ํ ์ฐธ๊ณ
์คํ๋ง๋ถํธ ๊ฒ์ํ API ์๋ฒ ๋ง๋ค๊ธฐ (1) - ํ๋ก์ ํธ ์์ฑ
์คํ๋ง๋ถํธ๋ก ๊ฒ์ํ API ์๋ฒ ๋ง๋ค๊ธฐ ํ๋ก์ ํธ๋ฅผ ์งํํด๋ณด๊ฒ ์ต๋๋ค. SpringBoot 2.x, JPA, Spring Security ๋ฑ์ ์ฌ์ฉํ์ฌ ๋ฌผํ ํ๋งค ๊ฒ์ํ์ ๊ตฌ์ถํด๋ณด๋ ค๊ณ ํฉ๋๋ค. ํ๋ฉด๋จ์ ๊ฐ๋ฐํ์ง ์๊ณ , API๋ง ์ ๊ณตํ
kukekyakya.tistory.com