본문 바로가기
IT/자바

Junit in Action 3판 - 4장) Junit4에서 Junit5로 전환하기

by 모띠 2025. 3. 15.
반응형

 

 

 

지금까지는 Junit과 그 최신버전인 Junit5에 대해 설명했다.

이번 장에서는 junit4를 junit5로 전환하는 방법에 대해 알아본다.

 

Junit 4 -> 5 전환

junit4를 junit5로 변경하기위해서는 아래와 같은 과정이 필요하다.

각 과정에 대해 자세히 알아본다.

 

1. 의존성을 교체한다.

2. 어노테이션을 변경한다.

3. 테스트 클래스와 메서드를 교체한다.

4. rule, runner를 extension으로 교체한다.

 

 

1. 의존성 교체

junit5를 사용하기 위해서는 의존성을 교체해야한다.

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.6.0</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.junit.jupiter</groupId>    
    <artifactId>junit-jupiter-engine</artifactId>    
    <version>5.6.0</version>    
    <scope>test</scope>
</dependency>

 

마이그레이션 작업이 끝날때까지는 4도 혼용해서 사용한다.

이런경우에는 junit5환경에서 4를 테스트할 수 있도록 빈티지 설정도 추가한다.

<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <version>5.6.0</version>
    <scope>test</scope>
</dependency>

 

 

2. 어노테이션 변경

junit4와 5의 어노테이션에는 변경점이 있으므로 새로운 어노테이션으로 변경한다.

특히, junit5로 넘어오면서 테스트메서드의 기본 접근 제어 수준이 public에서 디폴트로 완화되었다.

Junit 4 Junit 5
@BeforeAll, @BeforeEach @BeforeAll, @BeforeEach
@AfterAll, @AfterEach @AfterAll, @AfterEach
@Ignore @Disabled
@Category @Tag
Assert 클래스 사용
assertTaht 메서드 사용
Assertions 클래스 사용
assertThat 지원x, assertAll, assertThrows 메서드 추가
Assume 클래스 사용 Assumptions 클래스 사용

 

 

3. 테스트 클래스와 메서드 변경

assertThat 가 사용 불가능하므로 assertThat 대신에 Assertions 등으로 변경

하지만 hamcrest가 아니라 assertJ를 사용하는것을 적극 권장

아래는 tag를 예시로 코드 작성

@Tag("individual")
public class JUnit5CustomerTest {
    private String CUSTOMER_NAME = "John Smith";

    @Test
    void testCustomer() {
        Customer customer = new Customer(CUSTOMER_NAME);

        assertEquals("John Smith", customer.getName());
    }
}
@Tag("repository")
public class JUnit5CustomersRepositoryTest {
    private String CUSTOMER_NAME = "John Smith";
    private CustomersRepository repository = new CustomersRepository();

    @Test
    void testNonExistence() {
        boolean exists = repository.contains("John Smith");

        assertFalse(exists);
    }

    @Test
    void testCustomerPersistence() {
        repository.persist(new Customer(CUSTOMER_NAME));

        assertTrue(repository.contains("John Smith"));
    }
}

 

category가 코드에 입력하는것과 다르게 tag는 xml에 입력

<Configuration>
    <group>individual</group>
    <excludedGroup>repository</excludedGroup>
</Configuration>

 

 

 

4. rule과 runner -> extension 교체

junit 4 rule은 메서드 실행 전후에 추가 작업을 수행할 수 있는 컴포넌트

해당 추가 기능들은 전부 extension으로 교체하여 간단히 실행한다.

 

기존 정의된 rule 교체

1) 예외처리 assertThows

public class JUnit4RuleExceptionTester {
    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    private Calculator calculator = new Calculator();

    @Test
    public void expectIllegalArgumentException() {
        expectedException.expect(IllegalArgumentException.class);
        expectedException.expectMessage("Cannot extract the square root of a negative value");
        calculator.sqrt(-1);
    }

    @Test
    public void expectArithmeticException() {
        expectedException.expect(ArithmeticException.class);
        expectedException.expectMessage("Cannot divide by zero");
        calculator.divide(1, 0);
    }
}

 

assertThrows를 사용하여 간단히 예외 검증이 가능하다.

public class JUnit5ExceptionTester {
    private Calculator calculator = new Calculator();

    @Test
    public void expectIllegalArgumentException() {
        Throwable throwable = assertThrows(IllegalArgumentException.class, () -> calculator.sqrt(-1));
        assertEquals("Cannot extract the square root of a negative value", throwable.getMessage());
    }

    @Test
    public void expectArithmeticException() {
        Throwable throwable = assertThrows(ArithmeticException.class, () -> calculator.divide(1, 0));
        assertEquals("Cannot divide by zero", throwable.getMessage());
    }
}

 

 

2) 임시 디렉토리 @TempDir

 

기존에는 임시디렉토리를 만들고 테스트 후에 자동삭제를 위해서 TemporaryFolder라는 룰을 사용했다.

public class JUnit4RuleTester {
    @Rule
    public TemporaryFolder folder = new TemporaryFolder();

    @Test
    public void testTemporaryFolder() throws IOException {
        File createdFolder = folder.newFolder("createdFolder");
        File createdFile = folder.newFile("createdFile.txt");
        assertTrue(createdFolder.exists());
        assertTrue(createdFile.exists());
    }
}

 

하지만, @TempDir을 사용하면 간단히 가능하다.

public class JUnit5TempDirTester {
    @TempDir
    Path tempDir;

    private static Path createdFile;

    @Test
    public void testTemporaryFolder() throws IOException {
        assertTrue(Files.isDirectory(tempDir));
        createdFile = Files.createFile(tempDir.resolve("createdFile.txt"));
        assertTrue(createdFile.toFile().exists());
    }

    @AfterAll
    public static void afterAll() {
        assertFalse(createdFile.toFile().exists());
    }
}

 

 

사용자 정의 rule 전환

junit에서 기본적으로 제공해주는 rule 이외에 사용자가 직접 정의한 rule을 전환한다.

public class CustomRule implements TestRule { // TestRule을 구현해야함
    private Statement base;
    private Description description;

    @Override
    public Statement apply(Statement base, Description description) {
        this.base = base;
        this.description = description;
        return new CustomStatement(base, description);
    }

}
public class CustomStatement extends Statement {
    private Statement base;
    private Description description;

    public CustomStatement(Statement base, Description description) {
        this.base = base;
        this.description = description;
    }

    @Override
    public void evaluate() throws Throwable {
        System.out.println(this.getClass().getSimpleName() + " " + description.getMethodName() + " has started");
        try {
            base.evaluate();
        } finally {
            System.out.println(this.getClass().getSimpleName() + " " + description.getMethodName() + " has finished");
        }
    }
}
public class JUnit4CustomRuleTester {

    @Rule
    public CustomRule myRule = new CustomRule();

    @Test
    public void myCustomRuleTest() {
        System.out.println("Call of a test method");
    }
}

 

해당 rule은 아래의 extension으로 변환가능하다.

(AfterEachCallback, BeforeEachCallback 을 구현한다)

public class CustomExtension implements AfterEachCallback, BeforeEachCallback {
    @Override
    public void beforeEach(ExtensionContext extensionContext) throws Exception {
        System.out.println(this.getClass().getSimpleName() + " " + extensionContext.getDisplayName() + " has started");
    }

    @Override
    public void afterEach(ExtensionContext extensionContext) throws Exception {
        System.out.println(this.getClass().getSimpleName() + " " + extensionContext.getDisplayName() + " has finished");
    }
}

 

extension을 사용하여 전후처리 로깅을 간단히 처리.

@ExtendWith(CustomExtension.class)
public class JUnit5CustomExtensionTester {

    @Test
    public void myCustomRuleTest() {
        System.out.println("Call of a test method");
    }
}

 

반응형

댓글