Maven과의 통합 테스트

1. 개요

Maven은 Java 공간에서 가장 널리 사용되는 빌드 도구이며 통합 테스트는 개발 프로세스의 필수 부분입니다. 따라서 Maven과의 통합 테스트를 구성하고 실행하는 것은 자연스러운 선택입니다.

이 튜토리얼에서는 통합 테스트를 위해 Maven을 사용하고 단위 테스트에서 통합 테스트를 분리하는 다양한 방법을 살펴 봅니다.

2. 준비

데모 코드를 실제 프로젝트에 가깝게 만들기 위해 JAX-RS 애플리케이션을 설정합니다. 이 애플리케이션은 통합 테스트를 실행하기 전에 서버에 배포되고 나중에 해체됩니다.

2.1. Maven 구성

JAX-RS의 참조 구현 인 Jersey를 중심으로 REST 애플리케이션을 빌드 할 것입니다. 이 구현에는 몇 가지 종속성이 필요합니다.

 org.glassfish.jersey.containers jersey-container-servlet-core 2.27   org.glassfish.jersey.inject jersey-hk2 2.27 

여기와 여기에서 이러한 종속성의 최신 버전을 찾을 수 있습니다.

Jetty Maven 플러그인을 사용하여 테스트 환경을 설정합니다. 이 플러그인은 Maven 빌드 수명주기 의 사전 통합 테스트 단계 에서 Jetty 서버를 시작한 다음 통합 후 테스트 단계 에서 중지합니다 .

pom.xml 에서 Jetty Maven 플러그인을 구성하는 방법은 다음과 같습니다 .

 org.eclipse.jetty jetty-maven-plugin 9.4.11.v20180605   8999  quit 9000    start-jetty pre-integration-test  start    stop-jetty post-integration-test  stop    

Jetty 서버가 시작되면 포트 8999에서 수신 대기합니다 . stopKeystopPort 구성 요소는 플러그인의에 의해서만 사용되는 정지 목표와 가치는 우리의 관점에서 중요하지 않습니다.

Jetty Maven 플러그인의 최신 버전을 찾을 수있는 곳입니다.

주의해야 할 또 다른 점 은 pom.xml 파일 의 패키징 요소 를 war로 설정해야한다는 것입니다 . 그렇지 않으면 Jetty 플러그인이 서버를 시작할 수 없습니다.

war

2.2. REST 애플리케이션 생성

애플리케이션 엔드 포인트는 매우 간단합니다. GET 요청이 컨텍스트 루트에 도달하면 환영 메시지를 반환합니다.

@Path("/") public class RestEndpoint { @GET public String hello() { return "Welcome to Baeldung!"; } }

다음은 Jersey에 엔드 포인트 클래스를 등록하는 방법입니다.

package com.baeldung.maven.it; import org.glassfish.jersey.server.ResourceConfig; public class EndpointConfig extends ResourceConfig { public EndpointConfig() { register(RestEndpoint.class); } }

Jetty 서버가 REST 애플리케이션을 인식하도록하려면 클래식 web.xml 배포 설명자를 사용할 수 있습니다 .

  rest-servlet org.glassfish.jersey.servlet.ServletContainer  javax.ws.rs.Application com.baeldung.maven.it.EndpointConfig    rest-servlet /*  

이 설명자는 서버에서 인식 할 수 있도록 / src / main / webapp / WEB-INF 디렉토리 에 있어야합니다.

2.3. 클라이언트 측 테스트 코드

다음 섹션의 모든 테스트 클래스에는 단일 메서드가 포함되어 있습니다.

@Test public void whenSendingGet_thenMessageIsReturned() throws IOException { String url = "//localhost:8999"; URLConnection connection = new URL(url).openConnection(); try (InputStream response = connection.getInputStream(); Scanner scanner = new Scanner(response)) { String responseBody = scanner.nextLine(); assertEquals("Welcome to Baeldung!", responseBody); } }

보시다시피이 메서드는 이전에 설정 한 웹 애플리케이션에 GET 요청을 보내고 응답을 확인하는 것 외에는 아무것도하지 않습니다.

3. 실제 통합 테스트

통합 테스트에 대해 알아 두어야 할 중요한 점은 테스트 메서드를 실행하는 데 시간이 오래 걸린다는 것입니다.

결과적으로 기본 빌드 라이프 사이클에서 통합 테스트를 제외하여 프로젝트를 빌드 할 때마다 전체 프로세스가 느려지지 않도록해야합니다.

통합 테스트를 분리하는 편리한 방법은 빌드 프로필을 사용하는 것입니다. 이러한 종류의 구성을 사용하면 필요한 경우에만 적절한 프로필을 지정하여 통합 테스트를 실행할 수 있습니다.

다음 섹션에서는 빌드 프로필을 사용하여 모든 통합 테스트를 구성합니다.

4. Failsafe 플러그인으로 테스트

통합 테스트를 실행하는 가장 간단한 방법은 Maven failsafe 플러그인 을 사용하는 것 입니다.

기본적 메이븐으로 확실한 동안 플러그인 실행하는 단위 테스트 테스트 동안 단계, 안전 장치 에서 통합 테스트를 실행 플러그인 통합 테스트 단계 .

플러그인이 포함 된 테스트를 개별적으로 선택하기 위해 다른 패턴으로 테스트 클래스의 이름을 지정할 수 있습니다.

surefirefailsafe에 의해 적용되는 기본 명명 규칙 은 다르므로 이러한 규칙을 따라 단위 및 통합 테스트를 분리하면됩니다.

surefire 플러그인 의 실행 에는 이름이 Test로 시작 하거나 Test , Tests 또는 TestCase로 끝나는 모든 클래스가 포함됩니다 . 반대로 failsafe 플러그인은 이름이 IT로 시작 하거나 IT 또는 ITCase로 끝나는 클래스에서 테스트 메서드를 실행 합니다.

여기 에서 확실한 테스트 포함에 관한 문서를 찾을 수 있으며 , 여기에 안전 장치에 대한 문서가 있습니다 .

기본 구성으로 POM에 Failsafe 플러그인을 추가해 보겠습니다 .

 failsafe    maven-failsafe-plugin 2.22.0    integration-test verify       

이 링크는 안전 장치 플러그인 의 최신 버전을 찾을 수있는 곳 입니다.

With the above configuration, the following test method will be executed in the integration-test phase:

public class RestIT { // test method shown in subsection 2.3 }

Since the Jetty server starts up in the pre-integration-test phase and shuts down in post-integration-test, the test we have just seen passes with this command:

mvn verify -Pfailsafe

We can also customize the naming patterns to include classes with different names:

 maven-failsafe-plugin 2.22.0   **/*RestIT **/RestITCase   ... 

5. Testing With the Surefire Plugin

Apart from the failsafe plugin, we can also use the surefire plugin to execute unit and integration tests in different phases.

Let's assume we want to name all integration tests with the suffix IntegrationTest. Since the surefire plugin runs tests with such a name in the test phase by default, we need to exclude them from the default execution:

 maven-surefire-plugin 2.22.0   **/*IntegrationTest   

The latest version of this plugin is here.

We've taken all test classes having a name ending with IntegrationTest out of the build lifecycle. It's time to put them back with a profile:

 surefire    maven-surefire-plugin 2.22.0   integration-test  test    none   **/*IntegrationTest        

Instead of binding the test goal of the surefire plugin to the test build phase, as usual, we bound it to the integration-test phase. The plugin will then kick in during the integration testing process.

Notice that we must set an exclude element to none to override the exclusion specified in the base configuration.

Now, let's define an integration test class with our naming pattern:

public class RestIntegrationTest { // test method shown in subsection 2.3 }

This test will be running with the command:

mvn verify -Psurefire

6. Testing With the Cargo Plugin

We can use the surefire plugin with the Maven cargo plugin. This plugin comes with built-in support for embedded servers, which are very useful for integration testing.

More details about this combination can be found here.

7. Testing With JUnit's @Category

A convenient way to selectively execute tests is to leverage the @Category annotation in the JUnit 4 framework. This annotation lets us exclude particular tests from unit testing, and include them in integration testing.

First off, we need an interface or class to work as a category identifier:

package com.baeldung.maven.it; public interface Integration { }

We can then decorate a test class with the @Category annotation and Integration identifier:

@Category(Integration.class) public class RestJUnitTest { // test method shown in subsection 2.3 }

Rather than declaring the @Category annotation on a test class, we can also use it at the method level to categorize individual test methods.

Excluding a category from the test build phase is simple:

 maven-surefire-plugin 2.22.0  com.baeldung.maven.it.Integration  

Including the Integration category in the integration-test phase is also straightforward:

 category    maven-failsafe-plugin 2.22.0   **/*  com.baeldung.maven.it.Integration     integration-test verify       

We can now run integration tests with a Maven command:

mvn verify -Pcategory

8. Adding a Separate Directory for Integration Tests

It's desirable at times to have a separate directory for integration tests. Organizing tests this way allows us to entirely isolate integration tests from unit tests.

We can use the Maven build helper plugin for this purpose:

 org.codehaus.mojo build-helper-maven-plugin 3.0.0   add-integration-test-source generate-test-sources  add-test-source    src/integration-test/java     

Here is where we can find the latest version of this plugin.

The configuration we've just seen adds a test source directory to the build. Let's add a class definition to that new directory:

public class RestITCase { // test method shown in subsection 2.3 }

It's time to run integration tests in this class:

mvn verify -Pfailsafe

Maven failsafe 플러그인은 3.1 절에서 설정 한 구성으로 인해이 테스트 클래스의 메서드를 실행합니다.

테스트 소스 디렉토리는 종종 리소스 디렉토리와 함께 사용됩니다. 플러그인 구성 에 다른 실행 요소 에 이러한 디렉토리를 추가 할 수 있습니다 .

 ...  add-integration-test-resource generate-test-resources  add-test-resource     src/integration-test/resources     

9. 결론

이 기사에서는 Maven을 사용하여 Jetty 서버와의 통합 테스트를 실행하며 Maven surefirefailsafe 플러그인 의 구성에 중점을 둡니다 .

이 튜토리얼의 전체 소스 코드는 GitHub에서 찾을 수 있습니다.