Как протестировать основной класс приложения Spring -boot
У меня есть приложение spring-boot
, где стартовый класс @SpringBootApplication
выглядит как стандартный. Поэтому я создал множество тестов для всех своих функций и отправлю резюме в sonarqube, чтобы увидеть мой охват.
Для моего старшего класса Sonarqube говорит мне, что у меня всего 60% покрытия. Таким образом, средний охват не так хорош, как ожидалось.
![введите описание изображения здесь]()
Класс My Test является стандартным.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ElectronicGiftcardServiceApplication.class)
public class ElectronicGiftcardServiceApplicationTests {
@Test
public void contextLoads() {
}
}
Итак, как я могу проверить свой основной класс в классе стартеров моего приложения?
Ответы
Ответ 1
Все эти ответы кажутся излишними.
Вы не добавляете тесты, чтобы сделать метрический инструмент счастливым.
Загрузка Spring-контекста приложения занимает много времени. Не добавляйте его в каждую сборку для разработчиков, чтобы выиграть около 0,1% покрытия в вашем приложении.
Здесь вы не рассматриваете только 1 утверждение из 1 открытого метода. Он не представляет ничего с точки зрения охвата в приложении, где обычно пишутся тысячи заявлений.
Первый обходной путь: создайте класс приложения Spring Boot без объявленного компонента внутри. Если они у вас есть, переместите их в класс конфигурации (чтобы они по-прежнему покрывались модульным тестом). А затем проигнорируйте свой класс приложения 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[] {});
}
}
Ответ 2
Вы можете сделать что-то вроде этого
@Test
public void applicationContextLoaded() {
}
@Test
public void applicationContextTest() {
mainApp.main(new String[] {});
}
Ответ 3
У меня была та же цель (иметь тест, который запускает метод main()), и я заметил, что простое добавление метода теста, такого как @fg78nc, на самом деле "запускает" приложение дважды: один раз при помощи тестовой среды весенней загрузки, один раз через явный вызов mainApp.main(new String[] {})
, который я не нахожу элегантным.
В итоге я написал два тестовых класса: один с аннотацией @SpringBootTest
и пустой тестовый метод applicationContextLoaded(), другой без @SpringBootTest
(только RunWith(SpringRunner.class)
), который вызывает основной метод.
SpringBootApplicationTest
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() {
}
}
ApplicationStartTest
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
.
Ответ 4
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>your.awesome.package.Application</mainClass>
</configuration>
</plugin>
Если вы стремитесь к 100% -ному охвату, одна вещь, которую вы можете сделать, просто не имеет основного метода вообще. Вы все еще требуете класс, аннотированный с помощью @SpringBootApplication
, но он может быть пустым.
Будьте осторожны, хотя у него есть свои недостатки, и другие инструменты, которые полагаются на main
, могут сломаться.
Ответ 5
Вы можете Mock 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"});
}
}