Spring 통합 테스트 | JDBCTemplate

심삼진·2023년 5월 2일
0

Spring

목록 보기
8/12
post-thumbnail

스프링 통합 테스트

스프링 컨테이너와 DB까지 연결한 통합 테스트를 진행해봅시다.


[ 회원 서비스 스프링 통합 테스트 ]

package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.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.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
 public void 회원가입() throws Exception { //Given
 Member member = new Member();
 member.setName("hello");
 //When
 Long saveId = memberService.join(member);
 //Then
 Member findMember = memberRepository.findById(saveId).get();
 assertEquals(member.getName(), findMember.getName());
 }
 @Test
 public void 중복_회원_예외() throws Exception {
 //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("이미 존재하는 회원입니다.");
 }
}

@SpringBootTest : 스프링 컨테이너와 테스트를 함께 실행합니다.

@Transactional : 테스트 케이스에 이 애노테이션이 있으면 테스트 시작 전에 트랜잭션을 시작하고,
테스트 완료 후에 항상 롤백합니다.
이렇게 하면 DB에 데이터가 남지 않으므로 다음 테스트에 영향을 주지 않습니다.



테스트를 바로 실행하면 이미 spring이라는 데이터가 존재하므로 다음과 같은 메세지가 출력됩니다.


H2 콘솔에서 delete from member 로 데이터를 지워주고 실행해봅시다.


이전에 테스트를 많이 해서 다음과 같은 결과로 나왔습니다.

삭제 유무 관계없이 ID 번호가 올라간다고 하니 DB마다 결과가 다를 수 있습니다.





스프링 JdbcTemplate


순수 Jdbc와 동일한 환경설정을 하면 됩니다.
스프링 JdbcTemplate과 MyBatis 같은 라이브러리는 JDBC API에서 본 반복 코드를 대부분 제거해주지만 SQL은 직접 작성해야 합니다.


[ 스프링 JdbcTemplate 회원 리포지토리 ]

package hello.hellospring.repository;
import hello.hellospring.domain.Member;
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;
 public JdbcTemplateMemberRepository(DataSource dataSource) {
 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(), id);
 return result.stream().findAny();
 }
 @Override
 public List<Member> findAll() {
 return jdbcTemplate.query("select * from member", memberRowMapper());
 }
 @Override
 public Optional<Member> findByName(String name) {
 List<Member> result = jdbcTemplate.query("select * from member where 
name = ?", memberRowMapper(), name);
 return result.stream().findAny();
 }
 private RowMapper<Member> memberRowMapper() {
 return (rs, rowNum) -> {
 Member member = new Member();
 member.setId(rs.getLong("id"));
 member.setName(rs.getString("name"));
 return member;
 };
 }
}

[ JdbcTemplate을 사용하도록 스프링 설정 변경 ]

package hello.hellospring;
import hello.hellospring.repository.JdbcMemberRepository;
import hello.hellospring.repository.JdbcTemplateMemberRepository;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class SpringConfig {
 private final DataSource dataSource;
 public SpringConfig(DataSource dataSource) {
 this.dataSource = dataSource;
 }
 @Bean
 public MemberService memberService() {
 return new MemberService(memberRepository());
 }
 @Bean
 public MemberRepository memberRepository() {
// return new MemoryMemberRepository();
// return new JdbcMemberRepository(dataSource);
 return new JdbcTemplateMemberRepository(dataSource);
 }
}

성공적으로 테스트를 마쳤습니다.





학습중인 스프링 강의 : https://inf.run/pcut
스프링 실습 코드 저장소 : https://github.com/0pyaq0/Spring_Study.git

본 글은 2022년도에 작성한 기존 티스토리 블로그 글을 재업로드한 글입니다
기존 티스토리 블로그 : https://develop-about-leejin.tistory.com/

profile
주니어 백엔드 개발자

0개의 댓글