-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
{"assignment":"java-advanced-ru/docker"} | ||
{"assignment":"java-advanced-ru/test-containers"} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.gradle/ | ||
build/ |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
test: | ||
gradle test | ||
|
||
start: | ||
gradle bootRun |
Large diffs are not rendered by default.
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* |
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 | ||
} |
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"); | ||
} | ||
|
||
// Остальные тесты | ||
} |
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 |