저번 스프링 DB 접근 기술에 이어 진행합니다
스프링 통합 테스트
test - java - service - MemberServiceIntegrationTest 를 하나 생성합니다
package com.ujin.ujinspring.service;
import com.ujin.ujinspring.domain.Member;
import com.ujin.ujinspring.repository.MemberRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.transaction.annotation.Transactional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@SpringBootTest
@Transactional
class MemberServiceIntegrationTest {
@Autowired MemberService memberService;
@Autowired MemberRepository memberRepository;
@Test
void 회원가입() {
// given
Member member = new Member();
member.setName("spring");
//when
Long saveId = memberService.join(member);
// then
Member findMember = memberRepository.findById(saveId).get();
assertEquals(member.getName(), findMember.getName());
}
@Test
public void 중복_회원_예외() {
// given
Member member1 = new Member();
member1.setName("spring");
Member member2 = new Member();
member2.setName("spring");
// when
memberService.join(member1);
IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
}
}
처음에 실행시키면 DB에 spring 회원이 남아있기 때문에 이미 존재하는 회원입니다. 메세지가 출력됩니다
delect from member로 테이블 안에 내용을 지운 다음 실행시켜주어야 합니다
그런 다음 실행을 시켜준다면

이렇게 조회가 됩니다
(( ID는 이전에 4번 테스트를 해서 5로 출력되는데
삭제 유무와 관련없이 저렇게 출력된다고 합니다
어떤 DB에 따라 조금씩 다름 ))
이렇게 조회를 한 다음 다시 한 번 실행시켜주면

이렇게 문구가 다시 출력되는데
이유는 ID가 5인 spring이 member테이블에 들어있기 때문입니다.
(DB는 커밋을 하여 insert를 해야 DB에 반영이됩니다 이후 rollback을 이용하여 취소를 할 수 있습니다)
-> 이 방식을 사용하여 검증이 가능합니다
이러한 에러는 deleteAll 과 같은 메서드를 만들지 않아도 스프링이 제공하는
@Transactional
을 테스트케이스에 표기하면 테스트를 실행할 때 Transactional을 먼저 실행하고 DB에 데이터를 insert한 뒤
테스트가 끝나면 rollback을 해줍니다 (DB에 넣은 데이터가 지워짐)
그 전에 먼저 ID가 5인 spring을 지워줍니다.
회원가입() 메서드를 2번 실행시켜도 에러가 발생하지 않습니다

@SpringBootTest : 스프링 컨테이너와 테스트를 함께 실행한다.
( 진짜 spring으로 테스트를 하는 것)
@Transactional : 테스트 케이스에 이 애노테이션이 있으면, 테스트 시작 전에 트랜잭션을 시작하고, 테스트 완료 후에 항상 롤백한다. 이렇게 하면 DB에 데이터가 남지 않으므로 다음 테스트에 영향을 주지 않는다.
(테스트 하나마다 롤백함)
스프링 JdbcTemplate
순수 Jdbc와 동일한 환경설정을 하면 된다.
스프링 JdbcTemplate과 MyBatis 같은 라이브러리는 JDBC API에서
본 반복 코드를 대부분 제거해준다. 하지만 SQL은 직접 작성해야 한다.

JdbcTemplateMemberRepository 를 생성합니다
package com.ujin.ujinspring.repository;
import com.ujin.ujinspring.domain.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class JdbcTemplateMemberRepository implements MemberRepository {
private final JdbcTemplate jdbcTemplate;
@Autowired
public JdbcTemplateMemberRepository(DataSource dataSource){
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public Member save(Member member) {
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
Map<String, Object> parameters = new HashMap<>();
parameters.put("name", member.getName());
Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
member.setId(key.longValue());
return member;
}
@Override
public Optional<Member> findById(Long id) {
List<Member> result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper());
return result.stream().findAny();
}
@Override
public Optional<Member> findByName(String name) {
List<Member> result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
return result.stream().findAny();
}
@Override
public List<Member> findAll() {
return jdbcTemplate.query("select * from member", memberRowMapper());
}
private RowMapper<Member> memberRowMapper() {
return (rs, rowNum) -> {
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return member;
};
}
}
| 1 | @Autowired public JdbcTemplateMemberRepository(DataSource dataSource){ this.jdbcTemplate = new JdbcTemplate(dataSource); } |
| 2 | public JdbcTemplateMemberRepository(DataSource dataSource){ this.jdbcTemplate = new JdbcTemplate(dataSource); } |
생성자가 JdbcTemplateMemberRepository 하나이므로 1번에 들어있는 @Autowired를 아래 2번과 같이 생략할 수 있다
( 생성자가 하나일 경우에 생략 가능! )
@Bean
public MemberRepository memberRepository(){
// return new MemoryMemberRepository();
// return new JdbcMemberRepository(dataSource);
return new JdbcTemplateMemberRepository(dataSource);
}
SpringConflg.java를 수정해줍니다
그리고 실행시키면 에러가 나는데
@Override
public Optional<Member> findById(Long id) {
List<Member> result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id);
return result.stream().findAny();
}
JdbcTemplateMemberRepository에 Optional의 result가 id를 넘길 수 있도록 바꾸어줍니다.

테스트 성공~
'Spring' 카테고리의 다른 글
| 스프링 DB 접근 기술 ( 스프링 데이터 JPA ) AOP ( AOP가 필요한 상황 | AOP 적용 ) (0) | 2022.02.03 |
|---|---|
| 스프링 DB 접근 기술 3 ( JPA | 스프링 데이터 JPA ) (0) | 2022.01.28 |
| 스프링 DB 접근 기술 1 ( H2 데이터베이스 설치 | 순수 JDBC ) (0) | 2022.01.26 |
| 회원 관리 예제 - 웹 MVC 개발 ( 회원 웹 기능 - 홈 화면 추가 | 등록 | 조회 ) (0) | 2022.01.25 |
| 스프링 빈과 의존관계 ( 컴포넌트 스캔과 자동 의존관계 설정 | 자바 코드로 직접 스프링 빈 등록하기 ) (0) | 2022.01.24 |