programing

스프링 부트 테스트에서 이미 사용 중인 포트 해결 정의 포트

mbctv 2023. 3. 27. 21:32
반응형

스프링 부트 테스트에서 이미 사용 중인 포트 해결 정의 포트

Application Ready 이벤트를 듣고 외부 서비스를 호출하여 데이터를 가져온 다음 해당 데이터를 사용하여 일부 규칙을 클래스 경로에 푸시하여 실행하는 스프링 부트 응용 프로그램이 있습니다.로컬 테스트에서는 어플리케이션의 기동시에 정상적으로 동작하는 외부 서비스를 테스트하고 있습니다.

문제는 다음 중 하나에서 스프링부트 테스트 주석과 임베디드 Jetty 컨테이너를 사용하여 응용 프로그램을 실행함으로써 테스트하는 입니다.

  • 랜덤 포트
  • 정의된 포트

RANDOM PORT의 경우 어플리케이션 부팅 시 정의된 포트의 속성 파일에서 모의 서비스 URL을 픽업하고 임베디드 컨테이너가 랜덤으로 픽업되기 때문에 어디에 실행 중인지 알 수 없기 때문에 응답을 할 수 없습니다.

DEFINED PORT의 경우 첫 번째 테스트 케이스 파일은 정상적으로 실행되지만 다음 파일이 픽업되는 순간 포트가 이미 사용 중임을 나타내는 오류가 발생합니다.

테스트 케이스는 논리적으로 여러 파일로 분할되어 있으며 컨테이너가 규칙 로드를 시작하기 전에 외부 서비스를 호출해야 합니다.

정의된 포트를 사용하는 경우 테스트 파일 간에 임베디드 컨테이너를 공유하거나 테스트 케이스 실행 중 부팅 중에 랜덤 포트를 취득하기 위해 애플리케이션 코드를 리팩터링하려면 어떻게 해야 합니까?

어떤 도움이라도 주시면 감사하겠습니다.

응용 프로그램 시작 코드:

@Component
public class ApplicationStartup implements ApplicationListener<ApplicationReadyEvent> {

@Autowired
private SomeService someService;

@Override
public void onApplicationEvent(ApplicationReadyEvent arg0) {

    try {
        someService.callExternalServiceAndLoadData();
    }
    catch (Execption e) {}
    }
 }

테스트 코드 주석:테스트 1

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")
public class Test1 {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void tc1() throws IOException {.....}

테스트 코드 주석:테스트 2

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")
public class Test2 {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void tc1() throws IOException {.....}

여러 테스트에서 동일한 포트를 사용해야 하는 경우 테스트 클래스에 @DirtiesContext를 사용하여 주석을 달아 추가 테스트에 사용할 콘텍스트를 스프링이 캐싱하지 않도록 할 수 있습니다.

고객님의 경우:

@RunWith(SpringRunner.class)
@DirtiesContext
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:test-application.properties")

여기 토론에 대한 앤디 윌킨슨의 답변에서 인용한 것이 있다.

이것은 설계대로 동작하고 있습니다.Spring Framework의 테스트 프레임워크는 기본적으로 여러 테스트 클래스에서 재사용할 수 있도록 컨텍스트를 캐시합니다.(@TestPropertySource로 인해) 설정이 다른2개의 테스트가 있기 때문에 다른 어플리케이션콘텍스트를 사용합니다.첫 번째 테스트의 컨텍스트는 캐시되고 두 번째 테스트가 실행되는 동안 열린 상태로 유지됩니다.두 테스트 모두 Tomcat 커넥터에 동일한 포트를 사용하도록 구성되어 있습니다.그 결과, 두 번째 테스트 실행 시 첫 번째 테스트부터 커넥터와의 포트 충돌로 컨텍스트가 시작되지 않습니다.몇 가지 옵션이 있습니다.

  1. RANDOM_PORT 사용
  2. 콘텍스트의 설정이 같고 첫 번째 테스트의 콘텍스트를 두 번째 테스트에 재사용할 수 있도록 하려면 Test2에서 @TestPropertySource를 삭제합니다.
  3. 컨텍스트가 캐시되지 않도록 @DirtiesContext 사용

나는 같은 문제를 우연히 만났다.이 질문이 좀 오래된 건 알지만 도움이 될 수도 있습니다.

@SpringBootTest(webEnvironment=WebEnvironment)를 사용하는 테스트.RANDOM_PORT)는 다음 예시와 같이 @LocalServerPort 주석을 사용하여 실제 포트를 필드에 주입할 수도 있습니다.

출처 : https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/ #how-to-user-a-signed-syslog-port

다음에 나타내는 코드 예를 나타냅니다.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class MyWebIntegrationTests {

    @Autowired
    ServletWebServerApplicationContext server;

    @LocalServerPort
    int port;

    // ...

}

in application.properties

server.port=0

랜덤 포트에서 응용 프로그램을 실행합니다.

언급URL : https://stackoverflow.com/questions/42249791/resolving-port-already-in-use-in-a-spring-boot-test-defined-port

반응형