Skip to content

Commit

Permalink
submit java-advanced-ru/test-containers
Browse files Browse the repository at this point in the history
  • Loading branch information
hexlet-cli committed Jan 7, 2025
1 parent c490716 commit 4a86740
Show file tree
Hide file tree
Showing 31 changed files with 961 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .current.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"assignment":"java-advanced-ru/docker"}
{"assignment":"java-advanced-ru/test-containers"}
2 changes: 2 additions & 0 deletions java-advanced-ru/test-containers/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.gradle/
build/
3 changes: 3 additions & 0 deletions java-advanced-ru/test-containers/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions java-advanced-ru/test-containers/.idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions java-advanced-ru/test-containers/.idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions java-advanced-ru/test-containers/.idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions java-advanced-ru/test-containers/.idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions java-advanced-ru/test-containers/.idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions java-advanced-ru/test-containers/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions java-advanced-ru/test-containers/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
test:
gradle test

start:
gradle bootRun
75 changes: 75 additions & 0 deletions java-advanced-ru/test-containers/README.html

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions java-advanced-ru/test-containers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Test container

В прошлых домашних заданиях при тестировании мы использовали встроенную базу данных H2 в памяти. Это значительно упрощало тестирование приложения. Но в некоторых случаях мы можем захотеть проверить работу приложения с реальной базой данных, с той, которая будет использоваться при работе. В этом домашнем задании вам предстоит написать тесты для проверки работы приложения с базой данных PostgreSQL. Для этого мы будем использовать библиотеку Testcontainer. Она позволит нам в тестах запустить Docker контейнер с базой данных PostgreSQL. Для выполнения этого задания вам понадобится установленный Docker.

## Ссылки

* [Интеграция JUnit и Testcontainer](https://www.testcontainers.org/test_framework_integration/junit_5/)
* [Аннотация `@Testcontainers` – Активизирует автоматический старт и остановку контейнеров в отмеченном тестовом классе](https://javadoc.io/doc/org.testcontainers/junit-jupiter/latest/org/testcontainers/junit/jupiter/Testcontainers.html)
* [Аннотация `@Container` – Отмечает контейнер, который будет запущен в тестах](https://javadoc.io/doc/org.testcontainers/junit-jupiter/latest/org/testcontainers/junit/jupiter/Container.html)
* [Аннотация `@DynamicPropertySource` – позволяет динамически установить свойства приложения при интеграционных тестах](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/context/DynamicPropertySource.html)
* [Класс PostgreSQLContainer – служит для создания контейнера с базой данных PostgreSQL](https://javadoc.io/static/org.testcontainers/postgresql/1.9.1/org/testcontainers/containers/PostgreSQLContainer.html)

## build.gradle

## Задачи

* Изучите код в файле *build.gradle*. Посмотрите, какие зависимости необходимы для работы библиотеки Testcontainer

## src/main/java/exercise

В этой директории находится простое Spring Boot приложение, реализующее полный CRUD сущности.

## Задачи

* Изучите код приложения. Обратите внимание, что оно использует базу данных PostgreSQL.

## src/test/java/exercise/AppTest.java

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

## Задачи

* Отметьте тестовый класс необходимой аннотацией, чтобы обеспечить автоматический старт и остановку контейнеров.

* Сделайте так, чтобы каждый тест запускался в транзакции. Использовать транзакции при тестировании базы данных является хорошей практикой. Это делает тесты независимыми друг от друга.

* Создайте контейнер для базы данных PostgreSQL. Укажите имя базы данных, имя пользователя, пароль. Для наполнения базы данных тестовыми данными используйте скрипт *src/test/resources/init.sql*

* Дальше нам потребуется указать приложению, какой источник данных использовать. Так как база данных поднимается в контейнере, мы не можем заранее знать URL базы и использовать файл *properties.yml* для указания источника. В этом случае нам потребуется установить свойства приложения динамически. Создайте публичный статический метод, который будет устанавливать свойства приложения. Метод должен принимать на вход экземпляр класса `DynamicPropertyRegistry`. Отметьте его аннотацией `@DynamicPropertySource`. Метод должен устанавливать такие свойства, как url, имя пользователя и пароль для подключения к базе данных. Пример можно посмотреть в документации по этой аннотации.

На этом создание контейнера окончено. При запуске тестов будет автоматически запущен контейнер, создастся база данных и наполнится тестовыми данными.

* Допишите тесты, которые проверяют вывод списка всех пользователей, просмотр конкретного пользователя, редактирование и удаление пользователя. Проверьте только позитивные случаи.

* Запустите тесты и убедитесь, что они отработали корректно

## Подсказки

* Изучите пример в директории *examples*
34 changes: 34 additions & 0 deletions java-advanced-ru/test-containers/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
plugins {
id 'org.springframework.boot' version '3.0.6'
id 'io.spring.dependency-management' version '1.1.0'
id 'java'
id 'com.adarshr.test-logger' version '3.0.0'
id("io.freefair.lombok") version "8.6"
}

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'org.postgresql:postgresql'
implementation 'org.liquibase:liquibase-core'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'net.java.dev.jna:jna:5.13.0'

// Эти зависимости необходимы для работы Testcontainer
testImplementation 'org.testcontainers:junit-jupiter:1.18.3'
testImplementation 'org.testcontainers:testcontainers:1.18.3'
testImplementation 'org.testcontainers:postgresql:1.18.3'
}

test {
useJUnitPlatform()
}

testlogger {
showStandardStreams = true
}
66 changes: 66 additions & 0 deletions java-advanced-ru/test-containers/examples/Example.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
@SpringBootTest
@AutoConfigureMockMvc

// Аннотация позволяет автоматически запускать и останавливать в тестах все контейнеры
@Testcontainers
// Все тесты выполняем в транзакции
@Transactional
public class AppTest {

@Autowired
private MockMvc mockMvc;

// Аннотация отмечает контейнер, который будет автоматически запущен
@Container
// Создаём контейнер с СУБД PostgreSQL
// В конструктор передаём имя образа, который будет скачан с Dockerhub
// Если не указать версию, будет скачана последняя версия образа
private static PostgreSQLContainer<?> database = new PostgreSQLContainer<>("postgres")
// Создаём базу данных с указанным именем
.withDatabaseName("dbname")
// Указываем имя пользователя и пароль
.withUsername("sa")
.withPassword("sa")
// Скрипт, который будет выполнен при запуске контейнера и наполнит базу тестовыми данными
.withInitScript("script.sql");

// Так как мы не можем знать заранее, какой URL будет у базы данных в контейнере
// Нам потребуется установить это свойство динамически
@DynamicPropertySource
public static void properties(DynamicPropertyRegistry registry) {
// Устанавливаем URL базы данных
registry.add("spring.datasource.url", database::getJdbcUrl);
// Имя пользователя и пароль для подключения
registry.add("spring.datasource.username", database::getUsername);
registry.add("spring.datasource.password", database::getPassword);
// Эти значения приложение будет использовать при подключении к базе данных
}

// Тестируем приложение
@Test
void testCreatePerson() throws Exception {
// Добавляем нового пользователя
MockHttpServletResponse responsePost = mockMvc
.perform(
post("/people")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"firstName\": \"Jackson\", \"lastName\": \"Bind\"}")
)
.andReturn()
.getResponse();

assertThat(responsePost.getStatus()).isEqualTo(200);

// И проверяем, что пользователь добавился в базу
MockHttpServletResponse response = mockMvc
.perform(get("/people"))
.andReturn()
.getResponse();

assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getContentType()).isEqualTo(MediaType.APPLICATION_JSON.toString());
assertThat(response.getContentAsString()).contains("Jackson", "Bind");
}

// Остальные тесты
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit 4a86740

Please sign in to comment.