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 = []
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과의 관계