-
테스트 더블: 입력값테스팅 관련/개념 2020. 8. 9. 23:00
이어지는 시리즈
입력값으로 사용되는 3가지
1. 더미 객체
테스트 입력을 위해 파라미터로서 필요한 값.
어떤 값인지 중요치 않기때문에 무엇이든 대입한다.
null값을 제외하지 않음.
2. 테스트 스텁
여러 값들이 결과값을 제공할 수 있도록 하는 매우 단순화된 특수 목적 객체.
예) 특정 입력값들이 있는 테스트 스텁에 메소드를 호출하면, 결과값을 제공할 수 있다.
3. 페이크 객체
사용함에 있어, 값비싼 것을 저렴한 것으로 대체함.
예) 서버에 실행되는 외부 데이터베이스 → 인메모리 데이터베이스(비용적으로 저렴한 쿼리)
페이크 객체: 테스트 대상인 것처럼 실행되는 새로운 클래스를 작성
더미 객체, 테스트 스텁: 프레임워크(예. Mockito)를 사용하여, 매우 쉽게 생성
Mock
Mockito에서 더미 객체를 생성하기 위해 부르는 메소드.
mock(Name.class)
예. Employee emp1 = mock(Employee.class);Mockito에서는,
클래스가 맡는 역할과 어떻게 클래스가 구성되는지 사이에 차이점이 있다.
역할이 스텁일 수도, 모의 객체일 수도, 더미일 수도 있고, 전부 다일 수도 있다.
BUT, 구성하는 방법은 같다!
mock을 사용해서 (아무런 기능이 없고 기본값 필드를 포함하고 있는) 객체를 생성한다 → 더미 객체
// 더미: null이 아닌 객체 @Test public void testDummy() throws Exception { // 'mock' 메소드를 사용하여 더미 객체 생성 Employee empl1 = org.mockito.Mockito.mock(Employee.class); // Java import static을 사용 Employee empl2 = mock(Employee.class); // 더미 객체가 null인지 검증 org.junit.Assert.assertTrue(empl2.getFirstName() == null); // static import를 사용한 다양한 검증 assertTrue(empl2.getId() == 0); assertTrue(empl2.getSalary() == 0); assertTrue(empl2.getAddress() == null);
테스트하는 메소드에 파라미터가 있다면, 생성된 더미 객체에 추가적으로 기능(functionality)을 정의(define)한다 → 테스트 스텁
예. 더미 객체에 추가적으로 기능을 정의함으로서,
제대로 instantiate 하지 않아도 쿼리를 작성하여 결과값을 리턴할 수 있다.
// 스텁: 실제 객체를 유닛테스트에 사용하기에는 무겁고 어렵다 // findFlights의 분류 기능을 테스트한다고 가정해보자 // findFlights 메소드는 온라인 상태의 AirlineTravelService를 사용한다 (유닛테스트에 적합X) // AirlineTravelService 스텁을 생성하여 테스트하기 @Test public void testFindFlights() throws Exception { // 'mock' 메소드로 더미 객체 생성 AirlineTravleService stubSvc = mock(AirlineTravelService.class); // 데이터를 스텁 Date d = new Date(); List<Flight> l = new ArrayList<>(); Flight f1 = new Flight(d, "Delta", "DL1029", BigDecimal.valueOf(450.13)); Flight f2 = new Flight(d, "American", "AM245", BigDecimal.valueOf(375.13)); l.add(f1); l.add(f2); // 이 테스트에 필요한 행동 추가 when(stubSvc.findFlights(any(Date.class))) .thenReturn(l) .thenReturn(new ArrayList<>()); EmployeeTravelScheduler ets = new EmployeeTravelScheduler(stubSvc); Employee empl = createDummyEmployee(); assertEquals(ets.findFlights(empl, d).get(0), f2); // 더 저렴한 비행기 assertTrue(ets.findFlights(empl, d).isEmpty()); // 조건에 맞는 비행기 없음 // 스텁은 의존성 역전 패턴에 의존한다 (테스트 클래스에 의존성 주입) // 특정 객체 매치 테스트 @Test public void testFindFlightsMatching1() throws Exception { // 더미 객체 생성 AirlineTravelService stubSvc = mock(AirlineTravleService.class); // 데이터 스텁 Date d = new Date(); List<Flights> l = new Arraylist<>(); Flight f1 = new Flight(d, "Delta", "DL1029", BigDecimal.valueOf(450.13)); Flight f2 = new Flight(d, "American", "AM245", BigDecimal.valueOf(375.13)); l.add(f1); l.add(f2); // 10초 전 Date d2 = new Date(System.currentTimeMillis() - 10000); // 날짜 'd'에 맞는 매치, // 날짜 'd2'로 바꾸면, 테스트 fail! when(stubSvc.findFlights(d)) .thenReturn(l) .thenReturn(new ArrayList<>()); EmployeeTravelScheduler ets = new EmployeeTravelScheduler(stubSvc); Employee empl = createDummyEmployee(); assertEquals(ets.findFlights(empl, d).get(0), f2); assertTrue(ets.findFlights(empl, d).isEmpty()); }
'테스팅 관련 > 개념' 카테고리의 다른 글
SW 테스트 7가지 원리 (0) 2020.09.29 테스트 더블: 출력값 (0) 2020.08.09 테스트 더블: 소개 (0) 2020.08.09 소프트웨어 테스팅 프로세스 레벨 (0) 2020.06.20 '좋은' 테스트 계획의 중요성 (0) 2020.06.17