[SpringBoot] Освойте эти два свойства, чтобы ваш тестовый класс мог начаться быстрее

Spring Boot

Модульное тестирование является неотъемлемой частью разработки проекта.В проекте SpringBoot мы используем@SpringBootTestАннотация используется для обозначения тестового класса, и каждый метод тестируется индивидуально после внедрения класса реализации этого интерфейса в тестовый класс.

Например, следующий пример тестового класса:

@SpringBootTest
public class HelloServiceTests {
    
    @Autowired
    private IHelloSerive helloService;
    
    @Test
    public void testHello() {
        // ...
    }
}

Но по мере роста объема кода в проекте вы обнаружите, что скорость запуска тестового класса становится все медленнее и медленнее, и в большинстве случаев это просто тестирование метода класса реализации, например, тестирование категории DAO.persistметод.

По факту,@SpringBootTestАннотация также предоставляет два параметра, правильное использование которых может ускорить запуск тестового класса.

1. webEnvironment

Это свойство определяет, должен ли тестовый класс запускатьwebСреда, грубо говоря, стоит ли начинатьTomcatконтейнер, необязательные значения:

  • MOCK запускает фиктивную среду сервлета, которая используется по умолчанию.
  • RANDOM_PORT, запустите контейнер Tomcat и прослушивайте случайный номер порта
  • DEFINED_PORT, запустите контейнер Tomcat и прослушивайте порт, определенный в файле конфигурации (если он не определен, по умолчанию будет прослушиваться порт 8080).
  • NONE, не запускать контейнер Tomcat

Если метод, который вы хотите протестировать, не требует контейнера Tomcat, например:

  • Протестируйте CRUD для класса DAO
  • Протестируйте бизнес-метод класса Service
  • Протестируйте общедоступный метод класса Util
  • Проверка того, что класс файла конфигурации считывает правильное значение
  • ... ...

Просто указав@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)можно добиться эффекта ускорения. В это время при запуске тестового класса инициализируется только контекст Spring, а контейнер Tomcat больше не запускается:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class HelloServiceTests {
    
    @Autowired
    private IHelloSerive helloService;
    
    @Test
    public void testHello() {
        // ...
    }
}

2. classes

Атрибут классов используется для указания коллекции классов, которую необходимо загрузить для запуска тестового класса. Если он не указан, он будет загружен по умолчанию.@SpringBootConfigurationКласс аннотации аннотации.

упомянул@SpringBootConfigurationВы можете быть незнакомы, на самом деле@SpringBootApplicationЭта аннотация введена в исходный код:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    // ...
}

То есть, если мы не укажем атрибут классов, количество bean-компонентов, которые необходимо загрузить при запуске тестового класса, и начальный класс, который необходимо запустить в обычном режиме один раз (т.@SpringBootApplicationАннотированные классы) загружают одинаковое количество bean-компонентов.

Если в вашем проекте много бинов, особенно следующие:

  • Существует класс реализации для CommandLineRunner.
  • использовать@PostConstructАннотировать класс, указывающий метод инициализации

Эти классы будут запускать свой собственный бизнес-код или код инициализации в процессе инициализации программы, тем самым задерживая выполнение тестового метода.

В этом случае, когда мы пишем тестовый класс, если мы знаем, какие бины будут использоваться этим тестовым классом, мы можем указать их в атрибуте классов, и тогда, когда мы запустим тестовый класс, в него будут загружены только нужные бины. контекст для более быстрого запуска. Например:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes={HelloServiceImpl.class})
public class HelloServiceTests {

    @Autowired
    private IHelloService helloService;
    
    @Test
    public void testHello() {
        // ...
    }
}

Даже если в это время в проекте есть другой Бин, в его методе инициализации что-то вродеThread.sleep(10000)И так далее не повлияет, т.к. бин вообще не загружается и не инициализируется.


Наконец, обратите внимание, что если ваша версия JUnit 4.x, вам также необходимо добавить новый тестовый класс.@RunWith(SpringRunner.class)аннотация.