-
@SpringBootTestλ ν΅ν© ν μ€νΈλ₯Ό μ 곡νλ κΈ°λ³Έμ μΈ μ€νλ§ λΆνΈ ν μ€νΈ μ΄λ Έν μ΄μ -
μ€μ μ μμλ‘ λ°κΎΈμ΄μ ν μ€νΈ ν μ μλ€.
-
μ€μ κ΅λλλ μ ν리μΌμ΄μ κ³Ό λκ°μ΄ μ ν리μΌμ΄μ 컨ν μ€νΈλ₯Ό λ‘λνμ¬ ν μ€νΈνλ€.
-
@RunWith:JUintμ λ΄μ₯λ λ¬λλ₯Ό μ¬μ©νλ λμ μ΄λ Έν μ΄μ μ μ μλ λ¬λ ν΄λμ€λ₯Ό μ¬μ©νλ€. !κΌ λΆμ¬μΌνλ€! -
νλΌλ―Έν°
- value : ν μ€νΈκ° μ€νλκΈ° μ μ μ μ©ν νλ‘νΌν°λ₯Ό μ£Όμ μν¬ μ μλ€. - properties : ν μ€νΈκ° μ€νλκΈ° μ μ {key = value}νμμΌλ‘ νλ‘νΌν°λ₯Ό μΆκ°ν μ μλ€. - classes : μ ν리μΌμ΄μ 컨ν μ€νΈμ λ‘λν ν΄λμ€λ₯Ό μ§μ ν μ μλ€. λ°λ‘ μ§μ νμ§ μμΌλ©΄ `@SpringBootConfiguration`μ μ°Ύμμ λ‘λ - webEnvironment : μ ν리μΌμ΄μ μ΄ μ€νλ λμ μΉ νκ²½μ μ€μ ν μ μλ€.
- μΉμμ ν μ€νΈνκΈ° νλ 컨νΈλ‘€λ¬λ₯Ό ν μ€νΈνλ λ° μ ν©νλ€.
- μμ²κ³Ό μλ΅μ λν΄ ν μ€νΈν μ μλ€.
- μλμΌλ‘ ν μ€νΈνλ©° μλμΌλ‘ μΆκ°/μμ κ°λ₯
/com/havi/domain/Book.java
import java.time.LocalDateTime;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@NoArgsConstructor //νλΌλ―Έν°κ° μλ μμ±μλ₯Ό λ§λ€μ΄μ€λ€.
@Getter
public class Book{
private Integer idx;
private String title;
private LocalDateTime publishedAt;
@Builder //Builderν¨ν΄μ μ μ©ν κ°μ²΄ μμ± λ©μλ/ν΄λμ€λ₯Ό λ§λ€μ΄μ€λ€.
public Book(String title, LocalDateTime publishedAt){
this.title = title;
this.publishedAt = publishedAt;
}
}/com/havi/controller/BookController.java
package com.havi.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class BookController {
@Autowired
private BookService bookService;
@GetMapping("/books")
public String getBookList(Model model){
model.addAttribute("bookList",bookService.getBookList());
return "book";
}
}- /booksλ‘ μμ² μ νμ¬ BookService ν΄λμ€μ μ± λͺ©λ‘μ μμ²νμ¬ "bookList" λΌλ ν€κ°μΌλ‘ λ°μ΄ν°κ°μ λκΈ°λ 컨νΈλ‘€λ¬λ₯Ό λ§λ λ€. λ°νλλ λ·° μ΄λ¦μ 'book'μ΄λ€.
/com/havi/service/BookService.java
package com.havi.service;
import com.havi.domain.Book;
import java.util.List;
public interface BookService {
List<Book> getBookList();
}- ꡬν체λ₯Ό λ§λ€μ§ μκ³ λͺ© λ°μ΄ν°λ₯Ό μ΄μ©ν΄ ν μ€νΈλ₯Ό μ§ννλ€.
/com/havi/BookController.java
package com.havi;
import com.havi.controller.BookController;
import com.havi.domain.Book;
import com.havi.service.BookService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import java.time.LocalDateTime;
import java.util.Collections;
import static org.hamcrest.Matchers.contains;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@RunWith(SpringRunner.class)
@WebMvcTest(BookController.class)
public class BookControllerTest {
@Autowired
private MockMvc mvc;
@MockBean //κ°μ κ°μ²΄λ‘ λ체 (λͺ© κ°μ²΄)
private BookService bookService;
@Test
public void Book_MVC_ν
μ€νΈ() throws Exception{
Book book = new Book("Spring Boot Book", LocalDateTime.now());
given(bookService.getBookList()).willReturn(Collections.singletonList(book));
//getBookList()λ©μλμ μ€νμ λν λ°νκ°μ 미리 μ μ
mvc.perform(get("/books"))
.andExpect(status().isOk()) //HTTPμνκ°μ΄ 200μΈμ§ ν
μ€νΈ
.andExpect(view().name("book"))//λ°νλλ λ·°μ μ΄λ¦μ΄ 'book'μΈμ§ ν
μ€νΈ
.andExpect(model().attributeExists("bookList"))//λͺ¨λΈμ νλ‘νΌν° μ€ 'bookList'λΌλ νλ‘νΌν°κ° μ‘΄μ¬νλμ§ ν
μ€νΈ
.andExpect(model().attribute("bookList",contains(book)));//λͺ¨λΈμ νλ‘νΌν° μ€ 'bookList'λΌλ νλ‘νΌν°μ book κ°μ²΄κ° λ΄κ²¨μ Έ μλμ§ ν
μ€νΈ
}
}- MockMvcλ 컨νΈλ‘€λ¬ ν μ€νΈ μ λͺ¨λ μμ‘΄μ±μ λ‘λνλ κ²μ΄ μλ BookController κ΄λ ¨ λΉλ§ λ‘λνμ¬ κ°λ²Όμ΄ MVCν μ€νΈλ₯Ό μννλ€.
- JPA κ΄λ ¨ ν μ€νΈ μ€μ λ§ λ‘λνλ€.
- λ°μ΄ν°μμ€μ μ€μ μ΄ μ μμ μΈμ§, λ°μ΄ν°λ₯Ό μ λλ‘ μμ±,μμ ,μμ νλμ§ λ±μ ν μ€νΈκ° κ°λ₯νλ€.
- μ€μ λ°μ΄ν°λ₯Ό μ¬μ©νμ§ μκ³ ν μ€νΈ κ°λ₯νλ€.
@AutoConfigureTestDatabase- Replace.Any : μ¬μ©νλ©΄ κΈ°λ³Έμ μΌλ‘ λ΄μ₯λ λ°μ΄ν° μμ€λ₯Ό μ¬μ©νλ€.
- Replace.NONE : @ActiveProfilesμ μ€μ ν νλ‘νμΌ νκ²½κ°μ λ°λΌ λ°μ΄ν° μμ€κ° μ μ©λλ€.
- μλ μ€μ λ°©μ
- application.yml μ€μ μ spring.test.database.replace: NONE μΌλ‘ λ³κ²½
@DataJpaTest: ν μ€νΈκ° λλ λλ§λ€ μλμΌλ‘ ν μ€νΈμ μ¬μ©ν λ°μ΄ν° λ‘€λ°±- λ°μ΄ν° λ² μ΄μ€ μ¬μ© μ€μ
- spring.test.database.connection: H2
@AutoConfigureTestDatabase(connection = H2)
@Entity: ν΄λΉ ν΄λμ€κ° μν°ν°μμ μ리기 μν΄ μ¬μ©,μλκ²μμ ν΅νμ¬ μ΄ μ΄λ Έν μ΄μ μ΄ μ μΈ λ ν΄λμ€λ€μ μν°ν° λΉμΌλ‘ λ±λ‘νλ€.@Table: λ°μ΄ν°μ μ μ₯μ, ν μ΄λΈμ μλ―Ένλ€.@Id: μν°ν°μ κΈ°λ³Έν€λ₯Ό μλ―Ένλ€.@GeneratedValue: DBμ μν΄ μλμΌλ‘ μμ±λ κ°. μ€μ λ°μ΄ν°κ° μ μ₯λ λ μμ±λλ κ°μ΄λ€.@Column: νλμ ν μ΄λΈμ 컬λΌμ λ§€νμμΌμ€λ€.