paint-brush
Java 테스트: 주요 개념 [1부: 단위 테스트]~에 의해@gromspys
1,418 판독값
1,418 판독값

Java 테스트: 주요 개념 [1부: 단위 테스트]

~에 의해 Sergei Korneev10m2023/11/14
Read on Terminal Reader

너무 오래; 읽다

이 기사에서는 간단한 코드 예제, 매개변수화, 예외 테스트 및 주석을 포함하여 Java 단위 테스트의 주요 개념을 살펴보겠습니다.
featured image - Java 테스트: 주요 개념 [1부: 단위 테스트]
Sergei Korneev HackerNoon profile picture

단위 테스트는 코드의 신뢰성과 정확성을 보장하는 소프트웨어 개발의 기본 관행입니다. 이 기사에서는 간단한 코드 예제, 매개변수화, 예외 테스트, @Before , @BeforeEach , @After@AfterEach 와 같은 주석은 물론 모의 및 스텁 사용을 포함하여 Java 단위 테스트의 주요 개념을 살펴보겠습니다. .


또한 모의를 위한 인기 있는 Mockito 라이브러리를 소개하고 Maven 플러그인을 사용하여 코드 적용 범위를 측정하는 방법에 대한 지침을 제공합니다.

단위 테스트의 중요성

단위 테스트는 정확성을 확인하기 위해 개별 구성 요소 또는 코드 단위를 별도로 테스트하는 방법입니다. 주요 목표는 개발 프로세스 초기에 버그를 감지하고 수정하여 각 코드 단위가 예상대로 작동하도록 하는 것입니다.


예제에 사용할 수 있는 간단한 계산기 클래스를 만드는 것부터 시작해 보겠습니다. Calculator 클래스에는 기본 산술 연산이 포함되어 있습니다.

 public class Calculator { public int add(int a, int b) { return a + b; } public int subtract(int a, int b) { return a - b; } public int multiply(int a, int b) { return a * b; } public int divide(int a, int b) { return a / b; } }

간단한 단위 테스트 작성

Calculator 클래스에 대한 단위 테스트를 생성하려면 널리 사용되는 Java용 테스트 프레임워크인 JUnit 프레임워크를 사용할 수 있습니다. add 메소드에 대한 간단한 단위 테스트를 작성해 보겠습니다.

 import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; public class CalculatorTest { @Test public void testAdd() { Calculator calculator = new Calculator(); int result = calculator.add(2, 3); assertEquals(5, result); } }

이 테스트에서는 필요한 JUnit 클래스를 가져오고 @Test 로 테스트 메서드에 주석을 답니다. 그런 다음 Calculator 클래스의 인스턴스를 생성하고 add 메서드의 결과가 예상 값(5)과 동일하다고 주장합니다.

매개변수화된 테스트

매개변수화된 테스트를 사용하면 여러 입력 데이터 세트로 동일한 테스트 논리를 실행할 수 있습니다. 이는 다양한 입력 값을 사용하여 메서드를 테스트하는 데 유용합니다. JUnit에서 이를 수행하려면 @ParameterizedTest 주석을 사용하고 입력 값과 예상 결과를 매개변수로 제공할 수 있습니다. 예는 다음과 같습니다.

 import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import static org.junit.jupiter.api.Assertions.assertEquals; public class CalculatorTest { @ParameterizedTest @CsvSource({"2, 3, 5", "4, 7, 11", "0, 0, 0"}) public void testAdd(int a, int b, int expected) { Calculator calculator = new Calculator(); int result = calculator.add(a, b); assertEquals(expected, result); } }

이 예에서 @ParameterizedTest 주석을 사용하면 여러 입력 값 세트와 예상 결과를 CSV 형식으로 제공할 수 있습니다. 테스트 메소드는 각 조합에 대해 실행되어 add 메소드의 정확성을 보장합니다.

예외 테스트

코드가 오류를 적절하게 처리하는지 확인하려면 예외 테스트가 중요합니다. 예외 사례를 테스트하려면 JUnit에서 제공하는 assertThrows 메서드와 함께 @Test 주석을 사용할 수 있습니다.


예는 다음과 같습니다.

 javaCopy codeimport org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertThrows; public class CalculatorTest { @Test public void testDivideByZero() { Calculator calculator = new Calculator(); assertThrows(ArithmeticException.class, () -> calculator.divide(5, 0)); } }

이 테스트에서는 Calculator 클래스에서 숫자를 0으로 나누면 ArithmeticException 발생하는지 확인합니다.

주석 사용: @Before, @BeforeEach, @After 및 @AfterEach

@Before , @BeforeEach , @After@AfterEach 와 같은 주석은 테스트 환경을 설정하고 해제하는 데 사용됩니다. 이러한 주석은 일반적인 테스트 초기화 및 정리 작업을 관리하는 데 도움이 됩니다.


  • @Before@After 각각 테스트 클래스의 모든 테스트 메서드 전후에 한 번 실행됩니다.
  • @BeforeEach@AfterEach 각 테스트 메서드 전후에 실행됩니다.


예는 다음과 같습니다.

 import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; public class CalculatorTest { private Calculator calculator; @BeforeEach public void setUp() { calculator = new Calculator(); } @AfterEach public void tearDown() { calculator = null; } @Test public void testAdd() { int result = calculator.add(2, 3); assertEquals(5, result); } @Test public void testSubtract() { int result = calculator.subtract(5, 3); assertEquals(2, result); } }

이 예에서 setUp 메소드는 @BeforeEach 로 주석 처리되어 있으며 각 테스트 전에 Calculator 객체를 초기화합니다. @AfterEach 주석이 달린 tearDown 메소드는 각 테스트 후에 리소스를 정리합니다.

모의 및 스텁

모의 및 스텁은 데이터베이스나 웹 서비스와 같은 외부 종속성에서 테스트 중인 코드를 격리하려는 경우 단위 테스트에 필수적입니다. 이를 통해 이러한 종속성의 동작을 시뮬레이션할 수 있습니다.


  • 모의(Mock): 모의는 실제 객체의 동작을 모방하지만 사용자가 제어할 수 있는 객체입니다. 상호 작용을 기록하고 특정 메서드가 호출되는지 확인할 수 있습니다.


  • 스텁: 스텁은 메서드 호출에 대한 미리 준비된 응답을 제공합니다. 이는 미리 정의된 데이터를 반환하고 외부 시스템의 특정 동작을 시뮬레이션하는 데 사용됩니다.


외부 종속성과 관련된 메서드를 포함하도록 Calculator 클래스를 확장한 다음 해당 종속성을 시뮬레이션하기 위한 스텁을 생성해 보겠습니다.

 public class Calculator { private ExternalService externalService; public Calculator(ExternalService externalService) { this.externalService = externalService; } public int performComplexCalculation(int a, int b) { int result = externalService.multiply(a, b); return result + externalService.getConstant(); } }

업데이트된 Calculator 클래스에서 performComplexCalculation 곱셈과 상수 값 획득을 위해 ExternalService 사용합니다.


실제 ExternalService 에 의존하지 않고 Calculator 클래스를 테스트하기 위해 스텁을 생성하는 방법은 다음과 같습니다.

 import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.*; public class CalculatorTest { @Test public void testPerformComplexCalculation() { // Create a stub for ExternalService ExternalService externalServiceStub = new ExternalService() { @Override public int multiply(int a, int b) { return a * b; } @Override public int getConstant() { return 5; // Stubbed constant value } }; // Create the Calculator with the stubbed ExternalService Calculator calculator = new Calculator(externalServiceStub); // Test the performComplexCalculation method int result = calculator.performComplexCalculation(2, 3); assertEquals(11, result); // 2*3 + 5 (constant) = 11 } }

이 테스트에서는 필요한 메서드를 재정의하는 익명 클래스를 생성하여 테스트 메서드 내에서 ExternalService 스텁합니다. 이런 방식으로 Calculator 테스트 메서드는 ExternalService 의 실제 구현에 의존하지 않고 실행됩니다.


스텁은 클래스나 메서드의 특정 기능을 격리하고 테스트하기 위해 외부 시스템 또는 종속성의 동작을 시뮬레이션하는 데 유용합니다. 이를 통해 스텁의 동작을 제어하고 실제 외부 서비스 없이도 테스트 중인 장치에 집중할 수 있습니다.

조롱을 위한 Mockito 소개

Mockito는 모의 객체를 생성하고 관리하는 데 널리 사용되는 Java 라이브러리입니다. 외부 결제 게이트웨이와 상호작용하는 PaymentService 클래스가 있다고 가정해 보겠습니다. Mockito를 사용하여 결제 게이트웨이에 대한 모의를 만들 수 있습니다.

 import org.junit.jupiter.api.Test; import static org.mockito.Mockito.*; public class PaymentServiceTest { @Test public void testProcessPayment() { PaymentGateway paymentGateway = mock(PaymentGateway.class); PaymentService paymentService = new PaymentService(paymentGateway); when(paymentGateway.charge(100.0)).thenReturn(true); boolean result = paymentService.processPayment(100.0); assertTrue(result); verify(paymentGateway, times(1)).charge(100.0); } }

이 예에서는 모의 PaymentGateway 만들고 when 메소드를 사용하여 해당 동작을 정의합니다. 그런 다음 PaymentService 클래스에서 processPayment 메소드를 호출하고 charge 메소드가 예상 매개변수로 호출되었는지 확인합니다.

코드 적용 범위 및 Maven 플러그인

코드 적용 범위는 단위 테스트에서 실행되는 코드 줄, 분기 또는 문의 비율을 측정합니다. 이는 테스트되지 않은 코드와 추가 테스트가 필요할 수 있는 영역을 식별하는 데 도움이 됩니다.


Maven은 Java 프로젝트에 널리 사용되는 빌드 도구이며 JaCoCo와 같은 플러그인을 사용하여 Maven 프로젝트에 코드 적용 범위 분석을 통합할 수 있습니다. 프로젝트에 JaCoCo를 추가하는 방법은 다음과 같습니다.


  1. 프로젝트의 pom.xml 파일을 엽니다.
  2. JaCoCo Maven 플러그인 구성을 추가합니다.
 <build> <plugins> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.7</version> <executions> <execution> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>report</id> <phase>test</phase> <goals> <goal>report</goal> </goals> </execution> </executions> </plugin> </plugins> </build>


다음 명령을 사용하여 Maven 빌드를 실행합니다.

 mvn clean verify


빌드를 실행한 후 target/site/jacoco/index.html 파일에서 코드 적용 범위 보고서를 찾을 수 있습니다. 이 보고서는 단위 테스트의 코드 적용 범위에 대한 자세한 정보를 제공합니다.

결론

Java 단위 테스트는 코드의 신뢰성과 정확성을 보장하는 데 필수적인 방법입니다. JUnit 및 Mockito와 같은 도구를 사용하면 구성 요소에 대한 효과적인 단위 테스트 및 모의 테스트를 작성할 수 있습니다.


Maven 및 JaCoCo와 코드 적용 범위 분석을 통합하면 테스트가 코드 베이스의 상당 부분을 포괄하는지 확인할 수 있습니다. 정기적으로 단위 테스트를 테스트하고 유지 관리하면 고품질의 강력한 Java 애플리케이션을 생성하는 데 도움이 됩니다.


이 시리즈의 다음 부분에서는 전체 시스템이 올바르게 작동하는지 확인하기 위해 다양한 구성 요소와 서비스 간의 상호 작용을 테스트하는 소프트웨어 테스트의 중요한 측면인 통합 테스트를 살펴보겠습니다.


흥미진진한 통합 테스트의 세계로 빠져들게 될 2부도 계속 지켜봐 주시기 바랍니다!