programing

여러 스프링 부트 애플리케이션을 한 번에 테스트하는 방법

linuxpc 2023. 3. 2. 22:02
반응형

여러 스프링 부트 애플리케이션을 한 번에 테스트하는 방법

Spring Boot 어플리케이션이 2개 있는 멀티모듈 Maven 프로젝트가 있습니다.

부모

  • fooApp
  • 바앱
  • 시험

각각 독자적인 설정 컨텍스트가 있는 개별 스프링 부트애플리케이션을 같은 프로세스로 로드할 수 있는 테스트를 셋업하는 방법

public abstract class AbstractIntegrationTest {//test module

    protected FOO foo;
    protected BAR bar;

    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @IntegrationTest
    @Transactional
    @SpringApplicationConfiguration(classes = foo.Application.class)
    public class FOO {
        public MockMvc mockMvc;

        @Autowired
        public WebApplicationContext wac;

        @Before
        public void _0_setup() {
            MockitoAnnotations.initMocks(this);
            mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
            TestCase.assertNotNull(mockMvc);
        }

        public void login(String username) {
        }
    }

    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @IntegrationTest
    @Transactional
    @SpringApplicationConfiguration(classes = bar.Application.class)
    public class BAR {

        @Autowired
        public WebApplicationContext wac;

        public MockMvc restMvc;

        @Before
        public void _0_setup() {
            MockitoAnnotations.initMocks(this);
            restMvc = MockMvcBuilders.webAppContextSetup(wac).build();
            TestCase.assertNotNull(restMvc);
        }

        public void login(String username) {
        }
    }

    @Before
    public void _0_setup() {
        foo = new FOO();
        bar = new BAR();
    }
}

통합 테스트의 예

public class IntegrationTest extends AbstractIntegrationTest {

    @Test
    public void login() {
        foo.login("foologin");
        bar.login("barlogin");
    }

}

저는 @rainerhahnekamp가 달성하려는 것이 시스템/통합 테스트에 가깝다고 말한 것에 동의합니다.

하지만 여전히 이런 방식으로 테스트를 진행하길 원한다면, 저는 여전히 할 수 있다고 생각합니다.

번째로 알아야 할 중요한 것은 다음과 같습니다.
둘 다 ImportfooApp그리고.barApp안쪽으로 돌출하다test프로젝트는 클래스 로더가 두 프로젝트의 구성 파일을 사용할 수 있도록 하고 예측 불가능한 결과를 생성합니다.예: 둘 중 하나application.properties파일이 로드됩니다.따라서 2개의 다른 프로파일을 사용하여 2개의 분리된 구성 파일 설정을 로드해야 합니다.
프로젝트 파일이 겹치는 것과 같은 이유로 한 응용 프로그램에 의해 정의된 콩은 다른 응용 프로그램이 볼 수 있는 패키지에서 두 응용 프로그램에 모두 로드됩니다.

컨셉을 테스트하기 위해 각 프로젝트에 1개의 서비스와 1개의 나머지 컨트롤러를 만들었습니다.각 컨트롤러에는 '프로파일' 속성 파일이 있습니다.

바앱


@EnableAutoConfiguration(
    exclude = {SecurityAutoConfiguration.class,
    ManagementWebSecurityAutoConfiguration.class})
@SpringBootApplication
public class BarApp {


  public static void main(String[] args) {
    SpringApplication.run(BarApp.class, args);
  }

}

@Service
public class BarService {

  public String yield() {
    return "BarService !";
  }

}

@RestController
public class BarResource {

  private final BarService barService;

  public BarResource(BarService barService) {
    this.barService = barService;
  }

  @GetMapping("/bar")
  public String getBar() {
    return barService.yield();
  }

}

application-bar.properties:

server.port=8181

fooApp


@EnableConfigurationProperties
@SpringBootApplication
public class FooApp {
  
  public static void main(String[] args) {
    SpringApplication.run(FooApp.class, args);
  }

}

@Service
public class FooService {

  public String yield() {
    return "FooService !";
  }

}

@RestController
public class FooResource {

  private final FooService fooService;

  public FooResource(FooService fooService) {
    this.fooService = fooService;
  }

  @GetMapping("/foo")
  public String getFoo() {
    return fooService.yield();
  }

}

application-foo.properties:

server.port=8282

시험

class TestApps {

  @Test
  void TestApps() {
    // starting and customizing BarApp
    {
      SpringApplication barApp = new SpringApplication(BarApp.class);
      barApp.setAdditionalProfiles("bar"); // to load 'application-bar.properties'
      GenericWebApplicationContext barAppContext = (GenericWebApplicationContext) barApp.run();

      BarService barServiceMock = Mockito.mock(BarService.class);
      Mockito.doReturn("mockified bar !").when(barServiceMock).yield();
      barAppContext.removeBeanDefinition("barService");
      barAppContext.registerBean("barService", BarService.class, () -> barServiceMock);
    }

    // starting and customizing FooApp
    {
      SpringApplication fooApp = new SpringApplication(FooApp.class);
      fooApp.setAdditionalProfiles("foo"); // to load 'application-foo.properties'
      GenericWebApplicationContext fooAppContext = (GenericWebApplicationContext) fooApp.run();

      FooService fooServiceMock = Mockito.mock(FooService.class);
      Mockito.doReturn("mockified foo !").when(fooServiceMock).yield();
      fooAppContext.removeBeanDefinition("fooService");
      fooAppContext.registerBean("fooService", FooService.class, () -> fooServiceMock);
    }

    RestTemplate restTemplate = new RestTemplate();
    String barResourceUrl = "http://localhost:8181/bar";
    ResponseEntity<String> barResponse = restTemplate.getForEntity(barResourceUrl, String.class);

    String fooResourceUrl = "http://localhost:8282/foo";
    ResponseEntity<String> fooResponse = restTemplate.getForEntity(fooResourceUrl, String.class);

    System.out.println(barResponse.getBody());
    System.out.println(fooResponse.getBody());
  }

}

테스트를 실행하면 다음과 같은 결과가 생성됩니다.

mockified bar !
mockified foo !

덧붙여서, 당신의 프로젝트가 제 예처럼 단순할지는 의문이고, 제가 앞서 강조했던 중요한 사안과 관련된 문제에 직면하게 될 것 같습니다.

를 설정할 필요가 있습니다.@ContextConfiguration두 앱을 모두 가리키다

2개의 패키지 com.foo.module1과 com.foo.module2를 지정하면 패키지별로 Configuration클래스를 작성해야 합니다.예를 들어 module1의 경우:

@SpringBootApplication public class Config1 {}

단일 패키지의 스프링빈만을 사용하여 응용 프로그램을 실행하는 경우 Spring Application Builder를 사용하여 실행할 수 있습니다.작업 코드 조각:

   new SpringApplicationBuilder(com.foo.module1.Config1.class)
     .showBanner(false)
     .run()

그러면 Config1을 사용하여 Spring이 부팅됩니다.Config1은 패키지에 @ComponentScan이 포함되어 있습니다(@SpringBootApplication에 포함되어 있습니다).

2개의 모듈을 모두 동시에 실행하는 등 전체 응용 프로그램을 실행하려면 상위 패키지 com에서 구성 클래스를 만들어야 합니다.푸우

아래에 설명한 경우, 스프링 부트스타터 등의 라이브러리로 인해 1개의 애플리케이션 내에서2개의 모듈을 실행하는 것이 바람직하지 않은 방법으로 서로 간섭할 가능성이 있는 경우, 생각할 수 있는 것은 2가지뿐입니다.

  1. OSGi 사용: 이 경우 문제가 완전히 해결되지 않을 수 있으며 셋업이 상당히 복잡해질 수 있습니다.
  2. 애플리케이션을 2개의 애플리케이션으로 분할하여 인터페이스를 만듭니다.스프링 부트는 마이크로 서비스 아키텍처에도 적합합니다.

언급URL : https://stackoverflow.com/questions/34547581/how-to-test-multiple-spring-boot-applications-in-one-test

반응형