일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- spring
- Greedy
- transaction
- AOP
- 인프런
- http
- 김영한
- jpa
- 백준
- 그리디
- JPQL
- QueryDSL
- Proxy
- 알고리즘
- Spring Boot
- JDBC
- kotlin
- 스프링 핵심 원리
- 스프링
- 스프링 핵심 기능
- java
- Exception
- db
- Thymeleaf
- pointcut
- 자바
- springdatajpa
- Android
- SpringBoot
- Servlet
- Today
- Total
개발자되기 프로젝트
JUnit-2(spring, lombok 활용) 본문
JUnit-1에서 작성한 내용을 spring에서는 어떻게 작성해야 하는지 알아보자.
1. DollarCalculator 수정
먼저 Spring에서 bean으로 관리하기 위해 @Component 지정.
그리고 이전 코드에서는 marketApi객체를 생성자에서 주입받아서 사용을 했었다.
DollarCalculator class가 @Component기 때문에 MareketApi class도 마찬가지로 @Component등록이 필요하다.
참고로 @RequiredArgsContructor는 final, @NotNull인 인필드 값만 생성자에 주입을 시켜준다.
@Component
@RequiredArgsConstructor
public class DollarCalculator implements ICalculator {
private int price = 1;
private final MarketApi marketApi; //@RequiredArgsContructor,,, final 지정..?
@Override
public void init(){
this.price = marketApi.connect();
}
@Override
public int sum(int x, int y) {
init();
x *=price;
y*=price;
return x+y;
}
@Override
public int minus(int x, int y) {
init();
x *=price;
y*=price;
return x-y;
}
}
2. Calculator class 수정
이 클래스도 마찬가지로 @Component로 지정한다.
이 클래스는 ICalculator 객체를 사용하는데, ICalculator interface의 후보군은 현재 DollarCalculator class밖에 없다.
따라서 spring에서 자동으로 DollarCalculator를 주입하게 된다.
@Component
@RequiredArgsConstructor
public class Calculator {
private final ICalculator iCalculator;
public int sum(int x, int y){
this.iCalculator.init();
return this.iCalculator.sum(x, y);
}
public int minus(int x, int y){
this.iCalculator.init();
return this.iCalculator.minus(x, y);
}
}
3. Controller 작성
* 들어가기 전에 Dto를 작성해보자.(Request, Response 객체)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Req {
private int x;
private int y;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Res {
private int result;
private Body response;
//JSON에 depth를 주기위해 조금 복잡하게
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Body{
private String resultCode = "OK";
}
}
calculator는 현재 @Component Calculator 말고 후보군이 없음.
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class CalculatorApiController {
private final Calculator calculator;
@GetMapping("/sum")
public int sum(@RequestParam int x, @RequestParam int y){
return calculator.sum(x, y);
}
@PostMapping("/minus")
public Res minus(@RequestBody Req req){
int result = calculator.minus(req.getX(), req.getY());
Res res = new Res();
res.setResult(result);
res.setResponse(new Res.Body());
return res;
}
}
4. test 코드 작성
* 주의사항 : test의 package가 실제 코드의 package, Application과 ApplicationTests 위치가 일치해야 인식 가능.
* 다른 코드도 동일한 위치에 작성해준다.
4-1. SpringCalculatorApplicationTests 수정
@SpringBootTest 를 붙여주면 실질적으로 Spring container가 올라가면서 전체적인 테스트가 가능해짐.
@SpringBootTest//
class SpringCalculatorApplicationTests {
@Test
void contextLoads() {
}
}
5. DollarCalcualtorTest 작성하기
DollarCalcualtor test를 위해서는 MarketApi, DallarCalculator가 필요함! import 시키자.
그리고 MarketApi는 위에서 @Component로 지정했다. 따라서 mocking처리를 위해서는 @MockBean으로 지정한다.
참고) @Autowired : spring이 관리하는 bean중 해당 객체의 타입과 일치하는 객체를 주입함.
@Import({MarketApi.class, DollarCalculator.class})
@SpringBootTest //spring boot 붙이는 순간 모든 bean이 등록됨.위에 import생략 가능
public class DollarCalculatorTest {
@MockBean //bean으로 관리되어있으니 ..
private MarketApi marketApi;
//스프링이 관리하고 있는 bean을 받겠다.
@Autowired //???뭐하는애냐
private DollarCalculator dollarCalculator;
@Test
public void dollarCalculatorTest(){
Mockito.when(marketApi.connect()).thenReturn(3000);
int sum = dollarCalculator.sum(10, 10);
int minus = dollarCalculator.minus(10, 10);
Assertions.assertEquals(60000, sum);
Assertions.assertEquals(0, minus);
}
}
여기까지 Calculator가 정상적으로 작동하는 것을 test 완료했다.
이어서 Controller가 정상적으로 작동하는지 확인해보자.
6. CalculatorApiControllerTest 작성
* 들어가기 전에 Dto를 작성해보자.(Request, Response 객체)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Req {
private int x;
private int y;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Res {
private int result;
private Body response;
//JSON에 depth를 주기위해 조금 복잡하게
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Body{
private String resultCode = "OK";
}
}
Web에서 테스트를 할 예정이기 때문에! @webMvcTest(테스트할 class) 붙여준다.
그리고 @webMvcTest는 @SpringBootTest와는 다르게 web에 필요한 것들만 로딩을 시키기 때문에, resource 줄일 수 있당.
MocMvc란? 웹 어플리케이션을 서버에 배포하지 않고 spring MVC의 동작을 재현할 수 있도록 하는 class.
@AutoConfigureWebMvc : MVC와 관련된 Bean을 올려줌.
MockMvc.perfom() : 요청을 전송하고 결과를 ResultActiosns 객체를 가져온다. andExpect()기능 제공.
전송할 request를 build하는법? MockMvcRequsestBuilder.method(uri).queryPara... 등등
ResultMatcher : 실행된 결과와 예상 값을 매칭시켜 준다.
controller가 작동하기 위해서는 Calculator와 DollarCalculator import가 필요하다.
@WebMvcTest(CalculatorApiController.class)
@AutoConfigureWebMvc //뭐하ㅡㄴ애냐
@Import({Calculator.class, DollarCalculator.class})
public class CalculatorApiControllerTest {
@MockBean
private MarketApi marketApi;
@Autowired //Mvc를 Mocking처리하고 주입 받겠다!
private MockMvc mockMvc;
//각 test 실행 전에 초기화 시킬꺼야
@BeforeEach
public void init(){
Mockito.when(marketApi.connect()).thenReturn(3000);
}
@Test
public void sumTest() throws Exception {
//http://localhost:8080/api/sum
//parameter
mockMvc.perform(
MockMvcRequestBuilders.get("http://localhost:8080/api/sum")
.queryParam("x", "10")
.queryParam("y", "10")
).andExpect(
MockMvcResultMatchers.status().isOk()
).andExpect(
MockMvcResultMatchers.content().string("60000")
).andDo(MockMvcResultHandlers.print());
}
@Test
public void minusTest() throws Exception {
Req req = new Req();
req.setX(10);
req.setY(10);
String json = new ObjectMapper().writeValueAsString(req);
mockMvc.perform(
MockMvcRequestBuilders.post("http://localhost:8080/api/minus")
.contentType(MediaType.APPLICATION_JSON) //Json형식을 입력받기 위해 지정
.content(json)
).andExpect(
MockMvcResultMatchers.status().isOk()
).andExpect(
//json path에서 result의 value는 0이어야함
MockMvcResultMatchers.jsonPath("$.result").value("0")
).andExpect(MockMvcResultMatchers.jsonPath("$.response.resultCode").value("OK")
).andDo(MockMvcResultHandlers.print());
}
}
'Spring Boot' 카테고리의 다른 글
Swagger (0) | 2021.05.30 |
---|---|
Mock MVC (0) | 2021.05.22 |
Lombok (0) | 2021.05.22 |
JUnit-3 : Jacoco (0) | 2021.05.22 |
Junit-1 (0) | 2021.05.22 |