logo

요즘 학부시절 배운 테스트를 복습하고 있습니다.

생각해보니 CHANGOOS도 테스트를 작성해야겠다는 생각이 들었습니다.

좋은 개발자가 되기 위한 하나의 과정으로 테스트코드를 습관적으로 작성하라고 하셨는데.. 반성하게 됩니다..

<br/>

학부시절에 JUnitMockito를 사용하여 테스트를 실습했었습니다.

<em>Mockito는 가상 객체를 말합니다. 테스트 하기위해서 가상의 객체가 필요할때 사용합니다.</em>

<em>A객체를 가상으로 만들어 x메소드를 호출할때 k값을 리턴해! 라고 설정하여 테스트에 필요한곳에 주입하여 사용합니다.</em>

<br/>

Web환경에서 URL요청을 어떻게 테스트해야하는지 생각이 떠오르지 않았습니다만..

역시나 Sping-MvcTest 라는 별도의 테스트 라이브러리가 존재하네요.

<br/>

<hr/>

다음과 같이 작성하였습니다.

<br/>

우선 pom.xml에 세가지 라이브러리를 추가했습니다. (Junit, Mockito, Spring-test)

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-all</artifactId>
			<version>1.10.19</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${org.springframework-version}</version>
			<scope>test</scope>
		</dependency>

<br/>

그럼이제 하나의 예를 통해 구현을 진행해봅니다.

**src/main/java에 **패키지를 작성하고, 코드를 짰다면

**src/test/java에 **동일한 패키지를 작성하고, 테스트 클래스를 만듭니다.

<br/>

기존의 **IntroduceController **클래스는 다음과 같습니다.

@Controller
public class IntroduceController {
	@Autowired
	private CommonStringService commonStringService;
	
	@RequestMapping(value = "/introduce")
	public String introduce(Model model) {
		String intro001 = commonStringService.get("INTRO", "001"); // 자기소개
		String intro002 = commonStringService.get("INTRO", "002"); // 이력내용
		
		model.addAttribute("intro001", intro001);
		model.addAttribute("intro002", intro002);
		
		return "introduce/introduce_view";
	}
}

<br/>

그리고 다음과 같이 **IntroduceControllerTest **클래스를 만들었습니다.

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/appServlet/**-context.xml")
public class IntroduceControllerTest {
	@Mock
	CommonStringService commonStringService;
	
	@InjectMocks
	private IntroduceController introduceController;
	
	private MockMvc mockMvc;
	
	@Before
	public void init() {
		MockitoAnnotations.initMocks(this);
		mockMvc = MockMvcBuilders.standaloneSetup(introduceController).build();
	}
	
}

다음은 기본 설정을 설명합니다. 타 테스트 클래스도 동일하게 작성하여 진행할 수 있을 것입니다.

  • ** 1 : SpringJUnit4ClassRunner 클래스를 테스트 클래스로 사용하도록 합니다.

  • 2 : 정의된 web.xml 설정이 아닌, 가상의 web.xml을 사용하도록 한다.

  • 3 : 테스트를 위한 xml 설정파일을 지정합니다.

  • 5 : Mock객체 설정합니다.

  • 8 : 정의된 Mock 객체를 해당 객체에 주입하도록 한다.

  • 11: URL을 호출하여 테스트 할 수있는 mockMvc 객체

  • 13 : Test를 수행하기 전, 수행해야할 메소드

  • 15 : Mockito 초기화

  • 16 : mockMvc 초기화

<br/>

<br/>

<em>** @RunWith 어노테이션은 왜 사용하지?</em>

<em>@RunWith는 JUnit 프레임워크의 테스트 실행 방법을 확장할 때 사용하는 애노테이션이다. SpringJUnit4ClassRunner라는 JUnit용 테스트 컨텍스트 프레임워크 확장 클래스를 지정해주면 JUnit이 테스트를 진행하는 중에 테스트가 사용할 애플리케이션 컨텍스트를 만들고 관리하는 작업을 진행해준다.</em>

<em>출처 : <a href="https://countryxide.tistory.com/17">https://countryxide.tistory.com/17</a></em>

<br/>

<br/>

<br/>

그럼 이제 테스트 코드를 짜야합니다.

테스트코드는 3A (Arrange, Act, Assert) 동작으로 작동합니다.

Arrange는 테스트를 하기 위한 준비, Act는 실제 동작, Assert는 동작 후 비교. 다음과 같이 테스트코드를 구현하였습니다.

	@Test
	public void testIntroduce() throws Exception {
        //Arrange
		when(commonStringService.get("INTRO", "001")).thenReturn("자기소개");
		when(commonStringService.get("INTRO", "002")).thenReturn("이력내용");
		
        
		mockMvc.perform(get("/introduce")) // Act
		.andExpect(status().isOk()) //Assert
		.andExpect(view().name("introduce/introduce_view"))
		.andExpect(model().attribute("intro001", "자기소개"))
		.andExpect(model().attribute("intro002", "이력내용"));
	}
  • 3 : 해당메소드에 다음 매개변수가 들어가면, "자기소개"를 리턴합니다.

  • 4 : 해당메소드에 다음 매개변수가 들어가면, "이력내용"을 리턴합니다.

  • 6 : "/introduce" URL을 GET 메소드를 통해 호출한다.

  • 7 : HTTP 상태값이 200인가?

  • 8 : 뷰의 이름이 "introduce/introduce_view" 인가?

  • 9 : Model의 "intro001" 값이 "자기소개"인가?

  • 10 : Model의 "intro002" 값이 "이력내용"인가?

<br/>

<br/>

이 코드를 베이스로 URL 요청에 대한 Controller 테스트 코드를 작성 할 수 있습니다.

Service 클래스는 비즈니스로직이니 JUnit 테스트 코드로 작성하면 될 것입니다.

<br/>

<br/>

<hr/>

MockMvc 여러 테스트

HTTP 여러 요청에 대하여

mockMvc.perform(get("URL"))
mockMvc.perform(get("URL").param("p","01"))
mockMvc.perform(post("URL"))
mockMvc.perform(post("URL").param("p","01"))
mockMvc.perform(fileUpload("URL"),file("name", byte[]))
<br/>
  • 1 : GET 메소드 호출

  • 2 : 파라미터와 함께 GET 메소드 호출

  • 3 : POST 메소드 호출

  • 4 : 파라미터와 함께 POST 메소드 호출

  • 5 : multipart 호출, 파일 포함

<br/>

<br/>

요청URL이 REDIRECT로 리턴되어지는 경우

mockMvc.perform(get("URL"))
		.andExpect(redirectedUrl("REDIRECT URL"))
		.andExpect(status().isFound());

<br/>

요청 URL이 RESPONSE BODY인 경우

mockMvc.perform(get("URL"))
		.andExpect(status().isOk())
		.andExpect(content().json("JSON STRING"));

이 경우에는 JSON을 비교해주는 Jsonassert 라이브러리가 필요합니다.

<br/>

CommentCount 0
이전 댓글 보기
등록
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
TOP