Я думаю, все 3 представленных варианта плохи, если вы собираетесь запустить правильный модульный тест .Модульное тестирование должно быть быстрым, вы должны быть в состоянии запустить сотни из них в секунду или около того (в зависимости от аппаратного обеспечения, конечно, но вы понимаете).Поэтому, когда вы говорите «Я начинаю весну для каждого теста» - это больше не юнит-тест.Запуск Spring для каждого теста - очень дорогая операция.
Интересно то, что ваш код CoffeeService
написан так, что он отлично тестируется: просто используйте какую-нибудь библиотеку, такую как Mockito, для насмешки над классом репозитория, и выможет проверить сервисную логику вообще без пружины.Вам не понадобится никакой весенний бегун, любые весенние аннотации.Вы также увидите, что эти тесты работают намного быстрее.
class MyServiceTest {
@Test
public void test_my_service_get_coffee_logic() {
// setup
CoffeeRepository repo = Mockito.mock(CoffeeRepository.class);
Mockito.when(repo.findByName("mocha")).thenReturn("coffeeFound");
CoffeeService underTest = new CoffeeService(repo);
// when:
String actualCoffee = underTest.getCoffee("mocha");
// then:
assertEquals(actualCoffee, "coffeeFound");
}
}
Теперь о библиотеке пружинных тестов
Вы можете думать об этом как о способе тестирования кода, который требует некоторых соединений с другимикомпоненты и его проблематично макетировать.Это своего рода интеграционный тест внутри той же JVM.Все способы, которые вы представили, запускают контекст приложения, и это очень сложная вещь на самом деле, на youtube есть целые сессии о том, что на самом деле происходит во время запуска контекста приложения - хотя, за рамками вопроса,Дело в том, что для запуска запуска контекста требуется время
@SpringBootTest
идет дальше и пытается имитировать процессы, добавленные средой Spring Boot для создания контекста: решает, что сканировать на основе структур пакета, загружает внешние конфигурациииз предопределенных расположений при необходимости запускаются автоконфигурационные пускатели и т. д. и т. д.
Теперь контекст приложения, который может загружать все компоненты в приложении, может быть очень большим, и для некоторых тестов он не требуется.Обычно это зависит от цели теста
Например, если вы тестируете остальные контроллеры (что вы правильно разместили все аннотации), вероятно, вам не нужно запускать соединения с БД.
Все представленные вами способы фильтруют, что именно следует запускать, какие компоненты загружать и вставлять друг в друга.
Обычно эти ограничения применяются к «слоям», а не к отдельным компонентам.(слои = уровень покоя, уровень данных и т. д.).
Второй и третий методы фактически одинаковы, они представляют собой разные способы «фильтрации» контекста приложения, сохраняя только необходимые компоненты.
Обновление:
Поскольку вы уже провели сравнение производительности методов:
Модульный тест = очень быстрый тест, его цель - проверить код, который выВы написали (или один из ваших коллег, конечно) Так что если вы запускаете Spring, это автоматически означает относительно медленный тест.Поэтому, чтобы ответить на ваш вопрос
Может ли использование @ContextConfiguration быть "модульным тестом"
Нет, не может, это интеграционный тест, который запускает только один класс весной.
Обычно мы не запускаем только один класс с Spring Framework.Какая польза от его запуска внутри контейнера Spring, если вы хотите протестировать код только одного класса (модуля)?Да, в некоторых случаях это может быть пара классов, но не десятки или сотни.
Если вы запускаете один класс с пружиной, то в любом случае вам придется высмеивать все его зависимости,можно сделать с помощью mockito ...
Теперь по вашим вопросам
@ ContextConfiguration против @SpringBootTest технические различия.
@SpringBootTest
имеет отношение к делутолько если у вас есть приложение Spring Boot.Эта среда использует Spring под капотом, но, в двух словах, поставляется со многими предопределенными рецептами / практиками того, как написать «инфраструктуру» приложения: - управление конфигурацией, - структура пакета, - подключаемость - ведение журнала - интеграция базы данных и т. Д..
Итак, Spring Boot устанавливает четко определенные процессы для работы со всеми вышеупомянутыми элементами, и если вы хотите запустить тест, имитирующий приложение весенней загрузки, вы используете аннотацию @SpringBootTest
. В противном случае (или если у вас только приложение с пружинным приводом, а не пружинный башмак) - не используйте его вообще.
@ContextConfiguration
это совсем другая вещь. В нем просто говорится, какие bean-компоненты вы хотели бы использовать в приложении, управляемом Spring (это также работает с загрузкой Spring)
Является ли «модульный тест» правильным способом использования @ContextConfiguration? Или нет?
Как я уже сказал - все, что связано с весенним тестированием, предназначено только для интеграционного тестирования, так что нет, это неправильный способ использования в модульных тестах. Для юнит-тестов используйте то, что совсем не использует пружину (например, mockito для насмешек и обычный тест джунта без пружинного бегуна).