Spring(2023-04-25)

권단비·2023년 4월 25일
0

Test방법

목록 보기
2/3

[02.통합테스트]

Mock Test : 웹브라우저

애너테이션 = 하나의 기능을 갖고 있는 함수

[HomeController.java]
package edu.global.ex.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
public class HomeController {

	@GetMapping("/")
	public String home() {
		return "home";
	}

	@GetMapping("/user/userHome")
	public void userHome() { // void는 return값이 없지만, userHome.jsp를 리턴함
		log.info("userHome ...");
	}
//상기 userHome함수는 하기와 동일한 의미이다.
//	@GetMapping("/user/userHome")
//	public String userHome() {
//		log.info("userHome ...");
//		return "user/userHome";
//	}

	@GetMapping("/admin/adminHome")
	public void adminHome() {
		log.info("adminHome ...");
	}
}
--------------------------------------------------------------------------
[HomeControllerTest.java]
package edu.global.ex.controller;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@SpringBootTest
@AutoConfigureMockMvc // 웹 애플리케이션에서 컨트롤러를 테스트 할 때, 서블릿 컨테이너를 모킹하기 위해서는 @WebMvcTest 또는 @AutoConfigureMockMvc를 사용하면 된다.
class HomeControllerTest {

	@Autowired
	private MockMvc mockMvc; // 웹브라우저 역할

	@Disabled
	@Test
	void testHome() throws Exception {
		log.info("testHome()");

		// @GetMapping("/") 테스트
		mockMvc.perform(MockMvcRequestBuilders.get("/"))
			   .andExpect(MockMvcResultMatchers.status().isOk())
			   .andDo(print());
	}

	@Disabled
	@Test
	@WithMockUser(username = "user", password = "user", roles = "USER") // (roles="USER") 권한만 할당해도 실행됨
	void testUserHome() throws Exception {
		log.info("testUserHome()");

		// @GetMapping("/") 테스트
		mockMvc.perform(MockMvcRequestBuilders.get("/user/userHome"))
			   .andExpect(MockMvcResultMatchers.status().isOk())
			   .andDo(print());
	}
	
	@Test
	@WithMockUser(username = "admin", password = "admin", roles = "ADMIN") // (roles="ADMIN") 권한만 할당해도 실행됨
	void testAdminHome() throws Exception {
		log.info("testAdminHome()");

		// @GetMapping("/") 테스트
		mockMvc.perform(MockMvcRequestBuilders.get("/admin/adminHome"))
			   .andExpect(MockMvcResultMatchers.status().isOk())
			   .andDo(print());
	}
}
==========================================================================
[결과]
MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /user/userHome
       Parameters = {}
          Headers = []
             Body = null
    Session Attrs = {SPRING_SECURITY_CONTEXT=SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=user, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_USER]], Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[ROLE_USER]]]}

Handler:
             Type = edu.global.ex.controller.HomeController
           Method = edu.global.ex.controller.HomeController#userHome()

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = user/userHome
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Language:"en", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = null
             Body = 
    Forwarded URL = /WEB-INF/views/user/userHome.jsp
   Redirected URL = null
          Cookies = []
--------------------------------------------------------------------------
MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /admin/adminHome
       Parameters = {}
          Headers = []
             Body = null
    Session Attrs = {SPRING_SECURITY_CONTEXT=SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=admin, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_ADMIN]], Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[ROLE_ADMIN]]]}

Handler:
             Type = edu.global.ex.controller.HomeController
           Method = edu.global.ex.controller.HomeController#adminHome()

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = admin/adminHome
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Language:"en", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = null
             Body = 
    Forwarded URL = /WEB-INF/views/admin/adminHome.jsp
   Redirected URL = null
          Cookies = []

[03.시스템테스트]

package edu.global.ex.vo;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import javax.sql.DataSource;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@SpringBootTest
class DataSourceTest {

	@Autowired
	private DataSource datasource; // 소스코드 확인

	@Test // Junit이 제공하는 기본적인 어노테이션
	// Connection Pool에서 기본적으로 제공하는 datasource
	//datasource는 connection 객체를 갖고 있음
	void dataSourcetest() {
		System.out.println(datasource);
		assertNotNull(datasource);
	}

	@Test
	void testConnection() throws Exception {
		System.out.println("DS=" + datasource);

		try (Connection conn = datasource.getConnection()) { // 해당 코드 꼭 넣기
			assertNotNull(conn); // toString 오버라이딩되었으면 문자 출력
			System.out.println("Cooooooooonn=" + conn);
			
			assertThat(conn).isInstanceOf(Connection.class);
			//Connection객체가 원본이 Connection.class인지 확인하는 문구

			assertEquals(100, getLong(conn, "select 100 from dual"));
			// assertTrue(0 < getLong(conn, "select count(*) from User"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private long getLong(Connection conn, String sql) {
		long result = 0;
		try (Statement stmt = conn.createStatement()) {
			ResultSet rs = stmt.executeQuery(sql);
			if (rs.next()) {
				result = rs.getLong(1);
			}
			rs.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
}
==========================================================================
[결과]
DS=HikariDataSource (null)
Cooooooooonn=HikariProxyConnection@1595870950 wrapping net.sf.log4jdbc.sql.jdbcapi.ConnectionSpy@326706d
|----|
|100 |
|----|
|100 |
|----|
HikariDataSource (HikariPool-1)

[트랜잭션]

#트랜잭션 설명
##1.트랜잭션의 의미
> 일련의 작업 단위
> 완전히 처리되거나 All-OR-Nothing

##2.소프트웨어에서의 트랜잭션 처리
> 기본적으로(전통적으로) 하나의 함수에 묶어서 처리함.
> 스프링의 경우 그 기준은 비지니스 로직을 처리하는 서비스 단에서의 함수로 묶어버림

###★1)방법 사용
###1)controller(view결정) 함수 1개 끌고옴 << service에서 (비지니스 로직 처리/기능) 댓글달기 << mapper에서 함수 2개 끌고옴
###2)controller 함수 2개 끌고옴 << service : 함수 2개 생성(step update/댓글 insert함수)

##3.스프링에서는 기본적으로 함수, 클래스, 인터페이스 위에 @Transactional로 롤백처리
> 그럼 롤백(트랜잭션은) 언제 일어나는가? → 해당 함수에서 에러, Exception(예외)가 일어났을때

##4.@Transactional과 Checked unChecked Exception과의 관계

0개의 댓글