spring-boot
Тестирование весной
Поиск…
Как протестировать приложение Spring Spring
У нас есть пример загрузки Spring, который хранит данные пользователя в MongoDB, и мы используем службы Rest для получения данных
Сначала есть класс домена, то есть POJO
@Document
public class User{
@Id
private String id;
private String name;
}
Соответствующий репозиторий на основе Spring Data MongoDB
public interface UserRepository extends MongoRepository<User, String> {
}
Затем наш пользовательский контроллер
@RestController
class UserController {
@Autowired
private UserRepository repository;
@RequestMapping("/users")
List<User> users() {
return repository.findAll();
}
@RequestMapping(value = "/Users/{id}", method = RequestMethod.DELETE)
@ResponseStatus(HttpStatus.NO_CONTENT)
void delete(@PathVariable("id") String id) {
repository.delete(id);
}
// more controller methods
}
И, наконец, наше приложение для загрузки Spring
@SpringBootApplication
public class Application {
public static void main(String args[]){
SpringApplication.run(Application.class, args);
}
}
Если, скажем так, что John Cena, The Rock и TripleHHH были единственными тремя пользователями в базе данных, запрос / пользователям дал бы следующий ответ:
$ curl localhost:8080/users
[{"name":"John Cena","id":"1"},{"name":"The Rock","id":"2"},{"name":"TripleHHH","id":"3"}]
Теперь, чтобы проверить код, мы проверим, работает ли приложение
@RunWith(SpringJUnit4ClassRunner.class) // 1
@SpringApplicationConfiguration(classes = Application.class) // 2
@WebAppConfiguration // 3
@IntegrationTest("server.port:0") // 4
public class UserControllerTest {
@Autowired // 5
UserRepository repository;
User cena;
User rock;
User tripleHHH;
@Value("${local.server.port}") // 6
int port;
@Before
public void setUp() {
// 7
cena = new User("John Cena");
rock = new User("The Rock");
tripleHHH = new User("TripleHH");
// 8
repository.deleteAll();
repository.save(Arrays.asList(cena, rock, tripleHHH));
// 9
RestAssured.port = port;
}
// 10
@Test
public void testFetchCena() {
String cenaId = cena.getId();
when().
get("/Users/{id}", cenaId).
then().
statusCode(HttpStatus.SC_OK).
body("name", Matchers.is("John Cena")).
body("id", Matchers.is(cenaId));
}
@Test
public void testFetchAll() {
when().
get("/users").
then().
statusCode(HttpStatus.SC_OK).
body("name", Matchers.hasItems("John Cena", "The Rock", "TripleHHH"));
}
@Test
public void testDeletetripleHHH() {
String tripleHHHId = tripleHHH.getId();
when()
.delete("/Users/{id}", tripleHHHId).
then().
statusCode(HttpStatus.SC_NO_CONTENT);
}
}
объяснение
- Как и любой другой тест Spring, нам нужен
SpringJUnit4ClassRunner
чтобы создать контекст приложения. -
@SpringApplicationConfiguration
аналогично аннотации@ContextConfiguration
в том, что оно используется для указания того, какой прикладной контекст (ы), который должен использоваться в тесте. Кроме того, он будет запускать логику для чтения определенных конфигураций Spring Spring, свойств и т. Д. -
@WebAppConfiguration
должен присутствовать, чтобы сообщить Spring, что дляWebApplicationContext
должен быть загруженWebApplicationContext
. Он также предоставляет атрибут для указания пути к корню веб-приложения. -
@IntegrationTest
используется, чтобы сообщить Spring Boot, что должен быть запущен встроенный веб-сервер. Предоставляя пары (пары) имени и значения, разделенные двоеточием или равным, любая переменная среды может быть переопределена. В этом примере"server.port:0"
переопределит настройку порта по умолчанию сервера. Обычно сервер будет использовать указанный номер порта, но значение 0 имеет особое значение. Когда указано как 0, он сообщает Spring Boot сканировать порты в среде хоста и запускать сервер на случайном доступном порту. Это полезно, если у нас есть разные службы, занимающие разные порты на машинах разработки и сервере сборки, которые потенциально могут столкнуться с портом приложения, и в этом случае приложение не запустится. Во-вторых, если мы создадим несколько тестов интеграции с различными контекстами приложений, они могут также столкнуться, если тесты выполняются одновременно. - У нас есть доступ к контексту приложения и вы можете использовать autowiring для ввода любого компонента Spring.
-
@Value("${local.server.port}”)
будет разрешен фактический номер порта, который используется. - Мы создаем некоторые объекты, которые мы можем использовать для проверки.
- База данных MongoDB очищается и повторно инициализируется для каждого теста, чтобы мы всегда проверяли достоверное состояние. Поскольку порядок тестов не определен, есть вероятность, что тест testFetchAll () завершится неудачно, если он выполняется после теста testDeletetripleHHH ().
- Мы рекомендуем Rest Assured использовать правильный порт. Это проект с открытым исходным кодом, который предоставляет Java DSL для тестирования остающихся услуг
- Тесты выполняются с помощью Rest Assured. мы можем реализовать тесты с помощью TestRestTemplate или любого другого http-клиента, но я использую Rest Assured, потому что мы можем писать краткую документацию с помощью RestDocs
Загрузка другого файла yaml [или свойств] или переопределение некоторых свойств
Когда мы используем @SpringApplicationConfiguration
он будет использовать конфигурацию из application.yml
[properties], которая в определенной ситуации не подходит. Поэтому для переопределения свойств мы можем использовать аннотацию @TestPropertySource
.
@TestPropertySource(
properties = {
"spring.jpa.hibernate.ddl-auto=create-drop",
"liquibase.enabled=false"
}
)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTest{
// ...
}
Мы можем использовать атрибут свойств @TestPropertySource
для переопределения конкретных свойств, которые мы хотим. В приведенном выше примере мы переопределяем свойство spring.jpa.hibernate.ddl-auto
для create-drop
. И liquibase.enabled
to false
.
Загрузка другого файла yml
Если вы хотите полностью загрузить другой файл yml для теста, вы можете использовать атрибут местоположений на @TestPropertySource
.
@TestPropertySource(locations="classpath:test.yml")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTest{
// ...
}
Альтернативно варианты
Опция 1:
Вы также можете загрузить другой файл yml, поместив yml- файл в test > resource
каталог test > resource
Вариант 2:
Использование аннотации @ActiveProfiles
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@ActiveProfiles("somename")
public class MyIntTest{
}
Вы можете видеть, что мы используем аннотацию @ActiveProfiles
и мы передаем значение somename как значение.
Создайте файл под названием application-somename.yml
и тест загрузит этот файл.