스프링 부트 응용 프로그램의 메인 클래스를 테스트하는 방법
는 나나 a a a가 있다spring-boot 이 있는 @SpringBootApplication스타터 클래스는 표준 클래스처럼 보입니다.그래서 저는 제 모든 기능에 대한 많은 테스트를 만들고, 저의 커버리지를 확인하기 위해 요약본을 음파탐지기로 보냈습니다.
내 선발 수업에서 소나크베는 내가 60%밖에 커버리지가 없다고 말했다.그래서 평균 커버리지가 기대만큼 좋지 않다.
내 테스트 클래스가 기본 클래스입니다.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ElectronicGiftcardServiceApplication.class)
public class ElectronicGiftcardServiceApplicationTests {
@Test
public void contextLoads() {
}
}
그럼 내 애플리케이션의 스타터 클래스에서 메인 클래스를 테스트하려면 어떻게 해야 하나요?
이 모든 답변들은 과잉으로 보입니다.
메트릭 도구를 만족시키기 위해 테스트를 추가하는 것은 아닙니다.
애플리케이션의 Spring 콘텍스트를 로드하는 데 시간이 걸립니다.각 개발자의 빌드에 추가하는 것만으로 어플리케이션의 커버리지를 약 0.1% 획득할 수 없습니다.
여기서는 하나의 공개 메서드에서 하나의 스테이트먼트만 다루지 않습니다.일반적으로 수천 개의 스테이트먼트가 작성되는 어플리케이션에서는 커버리지에 대해서는 아무것도 나타내지 않습니다.
첫 번째 회피책: Spring Boot 어플리케이션클래스를 bean 선언 없이 만듭니다.있는 경우 컨피규레이션클래스로 이동해 주세요(유닛테스트의 대상인 채로 해 주세요).다음으로 테스트 커버리지 설정에서 Spring Boot 어플리케이션클래스를 무시합니다.
번째 : 꼭 : 설명하다main()들어 조직적인 을 위한 개발자인 통합 를목적을 .
import org.junit.Test;
// Test class added ONLY to cover main() invocation not covered by application tests.
public class MyApplicationIT {
@Test
public void main() {
MyApplication.main(new String[] {});
}
}
이런 거 할 수 있어요.
@Test
public void applicationContextLoaded() {
}
@Test
public void applicationContextTest() {
mainApp.main(new String[] {});
}
나는 여기서 다른 방법으로 해결했다.은 Spring할 수 있기 에 Spring's Run으로 주석을 달았습니다.@lombok.Generated이제 음파탐지기가 테스트 범위를 계산할 때 이를 무시합니다.
other.@Generated 주석, 주석, 등javax.annotation.processing.Generated ★★★★★★★★★★★★★★★★★」javax.annotation.Generated동작할 수도 있지만 발행 티켓이 마감되어 테스트 할 수 없습니다.
package com.stackoverflow;
import lombok.Generated;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
@Generated
public static void main(String... args) {
SpringApplication.run(Application.class, args);
}
}
을, 것과 같은 수 , @fg78nc에 의해1회, @fg78nc에 , @fg78nc에 의해 어플리케이션이1회 됩니다.그리고 @fg78nc가 말한 것과 같은 테스트 방법을 추가하는 것만으로 어플리케이션이 실제로2회 "시작"되는 것을 알게 되었습니다.스프링 부트 테스트 프레임워크에 의해1회, 1회, 1회, 1회, 1회, 1회의 명시적인 호출에 의해mainApp.main(new String[] {})우아하지 않은 것 같아요
는 결국 두 개의 . 수업으로, 하나는 시험 수업이다. 하나는@SpringBootTest주석 및 빈 테스트 메서드 applicationContextLoaded()를 지정합니다.또 다른 테스트메서드는 다음과 같습니다.@SpringBootTest(만)RunWith(SpringRunner.class)메인 메서드를 호출합니다.
Spring Boot 어플리케이션시험
package example;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.boot.test.context.SpringBootTest;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootApplicationTest {
@Test
public void contextLoads() {
}
}
응용 프로그램 시작 테스트
package example;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
public class ApplicationStartTest {
@Test
public void applicationStarts() {
ExampleApplication.main(new String[] {});
}
}
전체적으로 응용 프로그램은 여전히 두 번 시작되지만, 현재 두 개의 테스트 클래스가 있기 때문입니다.물론 이 두 가지 테스트 방법만으로 과잉으로 보이지만 보통 더 많은 테스트가 클래스에 추가됩니다.SpringBootApplicationTest틈을 타서@SpringBootTest세우다.
위의 답변과 더불어 JUnit 5 및 Mockito 3.4+를 사용하는 경우 Spring Boot 응용 프로그램의 주요 방법을 테스트합니다.
try (MockedStatic<SpringApplication> mocked = mockStatic(SpringApplication.class)) {
mocked.when(() -> { SpringApplication.run(ElectronicGiftCardServiceApplication.class,
new String[] { "foo", "bar" }); })
.thenReturn(Mockito.mock(ConfigurableApplicationContext.class));
ElectronicGiftCardServiceApplication.main(new String[] { "foo", "bar" });
mocked.verify(() -> { SpringApplication.run(ElectronicGiftCardServiceApplication.class,
new String[] { "foo", "bar" }); });
}
Spring Application 클래스의 스태틱메서드 run()이 ElectronicGiftCardServiceApplication.main()을 호출할 때 예상되는 String 배열과 함께 호출되는지 확인합니다.
awgtek 및 Ramji Sridaran과 동일한 아이디어이지만, JUnit 4용 솔루션입니다.
모의할 수 있다SpringApplication이는 테스트 대상 방법의 종속성이기 때문입니다.여기를 보세요.예.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.boot.SpringApplication;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
@RunWith(PowerMockRunner.class)
public class ElectronicGiftcardServiceApplicationTest {
@Test
@PrepareForTest(SpringApplication.class)
public void main() {
mockStatic(SpringApplication.class);
ElectronicGiftcardServiceApplication.main(new String[]{"Hello", "World"});
verifyStatic(SpringApplication.class);
SpringApplication.run(ElectronicGiftcardServiceApplication.class, new String[]{"Hello", "World"});
}
}
junit 사용
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.springframework.boot.SpringApplication;
import static org.assertj.core.api.Assertions.*;
class WebsiteApplicationTests {
@Test
void testApplication() {
MockedStatic<SpringApplication> utilities = Mockito.mockStatic(SpringApplication.class);
utilities.when((MockedStatic.Verification) SpringApplication.run(WebsiteApplication.class, new String[]{})).thenReturn(null);
WebsiteApplication.main(new String[]{});
assertThat(SpringApplication.run(WebsiteApplication.class, new String[]{})).isEqualTo(null);
}
}
에 이러한 의존관계를 추가합니다.pom.xml
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.8.0</version>
<scope>test</scope>
</dependency>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>your.awesome.package.Application</mainClass>
</configuration>
</plugin>
100% 커버리지를 목표로 하고 있는 경우는, 메인 방법을 전혀 가지지 않는 것만으로 충분합니다.다음 항목에 주석을 단 클래스가 여전히 필요합니다.@SpringBootApplication비어있을 수 있습니다.
, 및 하시기 바랍니다.main부서질 수 있습니다.
이 Spring Application용 간단한 모의고사는 어떤 메서드도 호출하지 않고 스타터 앱만 테스트합니다.[PowerMockRunner.class 사용]
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.boot.SpringApplication;
@RunWith(PowerMockRunner.class)
@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"})
public class JobsAppStarterTest {
@Test
@PrepareForTest(SpringApplication.class)
public void testSpringStartUp() {
PowerMockito.mockStatic(SpringApplication.class);
SpringApplication.run(JobsAppStarter.class, new String[] {"args"});
JobsAppStarter.main(new String[] {"args"});
}
}
Spring Application 클래스를 소나 검사에서 제외하는 것이 권장되는 방법이라면 build.gradle에서 다음 구성을 사용하여 제외할 수 있습니다.
plugins {
id 'org.sonarqube' version '3.4.0.2513'
}
sonarqube {
properties {
property "sonar.exclusions", "**/*Application.java"
}
}
이 질문에 대한 답변은 매우 다양하지만, 여기에서 다루지 않은 사용 사례를 공유하면 재미있을 것 같습니다.기동시에 몇개의 속성을 검증하고 있습니다.이러한 속성이 잘못 설정되어 있으면, 애플리케이션이 기동하지 않게 됩니다.JUnit4에서는 이런 걸 할 수 있었는데
@ActiveProfiles("incorrect")
@SpringBoot
public class NetworkProbeApplicationTest {
@Test(expected=ConfigurationPropertiesBindException.class)
public void contextShouldNotLoadWhenPropertiesIncorrect() {
}
}
그러나 JUnit5에서는 @Test 주석에 "예상된" 값을 추가할 수 없으므로 다른 방법으로 수행해야 합니다.그리고 잘못된 속성 세트를 사용하여 응용 프로그램을 시작하고 싶었기 때문에 main() 인수로 사용할 프로파일을 전달해야 했습니다.실제로 문서화된 내용은 찾을 수 없지만 main() 메서드를 통해 인수를 전달하려면 인수 앞에 이중 하이픈을 붙이고 키와 값을 등호로 구분해야 합니다.완전한 테스트는 다음과 같습니다.
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesBindException;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class NetworkProbeApplicationTest {
@Test
public void contextShouldNotLoadWhenPropertiesIncorrect() {
Exception exception = assertThrows(ConfigurationPropertiesBindException.class, () -> {
SpringApplication.run(NetworkProbeApplication.class, "--spring.profiles.active=incorrect");
});
String expectedMessage = "Error creating bean with name 'dnsConfiguration': Could not bind properties to 'DnsConfiguration' : prefix=dns";
assertTrue(exception.getMessage().contains(expectedMessage));
}
}
언급URL : https://stackoverflow.com/questions/46650268/how-to-test-main-class-of-spring-boot-application
'source' 카테고리의 다른 글
| Oracle SQL, 여러 열 연결 + 텍스트 추가 (0) | 2023.03.16 |
|---|---|
| 팬더에 JSON이 두 개 이상 포함된 파일 로드 (0) | 2023.03.16 |
| 유형 스크립트로 반응 - React.forwardRef 사용 시 일반 정보 (0) | 2023.03.16 |
| 공급자가 Oracle 클라이언트 버전과 호환되지 않습니다. (0) | 2023.03.16 |
| WooCommerce에서 다운로드 가능한 제품 기능을 비활성화하는 방법 (0) | 2023.03.16 |
