-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
471 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.gradle/ | ||
build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
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' | ||
} | ||
|
||
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' | ||
compileOnly 'org.projectlombok:lombok' | ||
annotationProcessor 'org.projectlombok:lombok' | ||
|
||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
rootProject.name = 'test-container' |
13 changes: 13 additions & 0 deletions
13
java-advanced-ru/test-containers/src/main/java/exercise/App.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package exercise; | ||
|
||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
|
||
@SpringBootApplication | ||
public class App { | ||
|
||
public static void main(String[] args) { | ||
// Запускаем приложение | ||
SpringApplication.run(App.class, args); | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
java-advanced-ru/test-containers/src/main/java/exercise/controller/PeopleController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package exercise.controller; | ||
|
||
import exercise.model.Person; | ||
import exercise.repository.PersonRepository; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.PatchMapping; | ||
|
||
@RestController | ||
@RequestMapping("/people") | ||
@RequiredArgsConstructor | ||
public class PeopleController { | ||
|
||
// Автоматически заполняем значение поля | ||
private final PersonRepository personRepository; | ||
|
||
@GetMapping(path = "") | ||
public Iterable<Person> getPeople() { | ||
return this.personRepository.findAll(); | ||
} | ||
|
||
@PostMapping(path = "") | ||
public void createPerson(@RequestBody Person person) { | ||
this.personRepository.save(person); | ||
} | ||
|
||
@GetMapping(path = "/{id}") | ||
public Person getPerson(@PathVariable long id) { | ||
return this.personRepository.findById(id); | ||
} | ||
|
||
@DeleteMapping(path = "/{id}") | ||
public void deletePerson(@PathVariable long id) { | ||
this.personRepository.deleteById(id); | ||
} | ||
|
||
@PatchMapping(path = "/{id}") | ||
public void updatePerson(@PathVariable long id, @RequestBody Person person) { | ||
person.setId(id); | ||
this.personRepository.save(person); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
java-advanced-ru/test-containers/src/main/java/exercise/controller/WelcomeController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package exercise.controller; | ||
|
||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
public class WelcomeController { | ||
|
||
@GetMapping("/") | ||
public String root() { | ||
return "Welcome to Spring"; | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
java-advanced-ru/test-containers/src/main/java/exercise/model/Person.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package exercise.model; | ||
|
||
import lombok.Getter; | ||
import lombok.Setter; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.Table; | ||
|
||
@Getter | ||
@Setter | ||
@Entity | ||
@Table(name = "people") | ||
public class Person { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private long id; | ||
|
||
private String firstName; | ||
private String lastName; | ||
|
||
} |
11 changes: 11 additions & 0 deletions
11
java-advanced-ru/test-containers/src/main/java/exercise/repository/PersonRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package exercise.repository; | ||
|
||
import exercise.model.Person; | ||
import org.springframework.data.repository.CrudRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository | ||
public interface PersonRepository extends CrudRepository<Person, Long> { | ||
|
||
Person findById(long id); | ||
} |
17 changes: 17 additions & 0 deletions
17
java-advanced-ru/test-containers/src/main/resources/application.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
server: | ||
port: ${PORT:5000} | ||
|
||
logging: | ||
level: | ||
root: INFO | ||
|
||
spring: | ||
datasource: | ||
url: jdbc:postgresql://localhost:5432/hexlet | ||
username: sa | ||
password: sa | ||
jpa: | ||
show-sql: true | ||
|
||
liquibase: | ||
change-log: classpath:db/changelog/db.changelog-master.yaml |
21 changes: 21 additions & 0 deletions
21
java-advanced-ru/test-containers/src/main/resources/db/changelog/db.changelog-master.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
databaseChangeLog: | ||
- changeSet: | ||
id: 1 | ||
author: hexlet | ||
changes: | ||
- createTable: | ||
tableName: people | ||
columns: | ||
- column: | ||
name: id | ||
type: bigint | ||
autoIncrement: true | ||
constraints: | ||
primaryKey: true | ||
nullable: false | ||
- column: | ||
name: first_name | ||
type: varchar(255) | ||
- column: | ||
name: last_name | ||
type: varchar(255) |
61 changes: 61 additions & 0 deletions
61
java-advanced-ru/test-containers/src/test/java/exercise/AppTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package exercise; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.transaction.annotation.Transactional; | ||
import org.springframework.test.web.servlet.MockMvc; | ||
import org.springframework.mock.web.MockHttpServletResponse; | ||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; | ||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; | ||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; | ||
import org.springframework.http.MediaType; | ||
|
||
import org.testcontainers.junit.jupiter.Testcontainers; | ||
import org.testcontainers.junit.jupiter.Container; | ||
import org.springframework.test.context.DynamicPropertySource; | ||
import org.springframework.test.context.DynamicPropertyRegistry; | ||
import org.testcontainers.containers.PostgreSQLContainer; | ||
|
||
@SpringBootTest | ||
@AutoConfigureMockMvc | ||
|
||
// BEGIN | ||
|
||
// END | ||
public class AppTest { | ||
|
||
@Autowired | ||
private MockMvc mockMvc; | ||
|
||
// BEGIN | ||
|
||
// END | ||
|
||
@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"); | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
java-advanced-ru/test-containers/src/test/resources/application.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
spring: | ||
liquibase: | ||
enabled: false |
13 changes: 13 additions & 0 deletions
13
java-advanced-ru/test-containers/src/test/resources/init.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
CREATE TABLE people ( | ||
id bigint PRIMARY KEY GENERATED ALWAYS AS IDENTITY, | ||
first_name varchar(255), | ||
last_name varchar(255) | ||
); | ||
|
||
INSERT INTO | ||
people (first_name, last_name) | ||
VALUES | ||
('John', 'Smith'), | ||
('Jack', 'Doe'), | ||
('Jassica', 'Simpson'), | ||
('Robert', 'Lock'); |
Oops, something went wrong.