英文:
How to run Spring boot app's unit test on GitHub Action
问题
我有一个基本上执行CRUD操作的应用程序。我可以在本地运行单元测试,但在CI(GitHub Action)上失败了。我之所以出错是因为与PostgreSQL有关。在这里你可以看到错误信息。我无法修复它。你可以通过这个链接访问整个存储库。你可以在下面看到我的ci.yaml
文件;
name: CI
on:
pull_request:
push:
branches: [develop, main]
concurrency:
group: ci-${{ github.ref }}-group
cancel-in-progress: true
jobs:
default:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Update dependency graph
uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6
- name: Build Jar file
run: ./project-dev build-jar
- name: Save Jar file
uses: actions/upload-artifact@v3
with:
name: demo-0.0.1-SNAPSHOT
path: target/demo-0.0.1-SNAPSHOT.jar
retention-days: 1
请问有人可以帮助我在CI上运行我的单元测试吗?
英文:
I have an app that does CRUD basically. I am able to run my unit tests locally but on the CI(GitHub Action) it's failing. I am getting the error because of PostgreSQL. Here you can see the error. I couldn't be able to fix that. You can access the whole repository on this LINK. You can see my ci.yaml
file below;
name: CI
on:
pull_request:
push:
branches: [develop, main]
concurrency:
group: ci-${{ github.ref }}-group
cancel-in-progress: true
jobs:
default:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Update dependency graph
uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6
- name: Build Jar file
run: ./project-dev build-jar
- name: Save Jar file
uses: actions/upload-artifact@v3
with:
name: demo-0.0.1-SNAPSHOT
path: target/demo-0.0.1-SNAPSHOT.jar
retention-days: 1
Can someone help me to run my unit tests on the CI, please?
答案1
得分: 2
以下是翻译好的部分:
-
You need to make sure that the database runs.
- 你需要确保数据库正常运行。
-
Your program expects a Posgres DB named
school_management
to be available underlocalhost:5432
.- 你的程序期望在
localhost:5432
下有一个名为school_management
的 Posgres 数据库。
- 你的程序期望在
-
However, such a database isn't available in your script.
- 然而,在你的脚本中并没有这样的数据库。
-
For setting up the database, you could use the an existing action like this one :
- 为了设置数据库,你可以使用类似这个的现有操作:
-
Alternatively, you could use PosgreSQL service containers as described here:
- 或者,你可以使用如下所述的 PosgreSQL 服务容器:
-
However this makes it run using a different hostname so you have to change your
spring.datasource.url
tojdbc:postgresql://localhost:5432/school_management
or similar.- 但是这会使用不同的主机名来运行,因此你必须将你的
spring.datasource.url
更改为jdbc:postgresql://localhost:5432/school_management
或类似的内容。
- 但是这会使用不同的主机名来运行,因此你必须将你的
-
Integrated in your workflow, it could look like the following:
- 集成到你的工作流中,它可能如下所示:
-
Another possibility is to use an embedded database like H2 for tests.
- 另一个可能性是在测试中使用嵌入式数据库,如 H2。
英文:
You need to make sure that the database runs.
Your program expects a Posgres DB named school_management
to be available under localhost:5432
.
However, such a database isn't available in your script.
For setting up the database, you could use the an existing action like this one :
steps:
- uses: harmon758/postgresql-action@v1
with:
postgresql version: '11'
postgresql db: school_management
postgresql user: learning
postgresql password: sa123456
Alternatively, you could use PosgreSQL service containers as described here:
# Service containers to run with `container-job`
services:
# Label used to access the service container
postgres:
# Docker Hub image
image: postgres
# Provide the password for postgres
env:
POSTGRES_PASSWORD: sa123456
POSTGRES_USER: learning
POSTGRES_DB: school_management
# Set health checks to wait until postgres has started
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
However this makes it run using a different hostname so you have to change your spring.datasource.url
to jdbc:postgresql://localhost:5432/school_management
or similar.
Integrated in your workflow, it could look like the following:
name: CI
on:
pull_request:
push:
branches: [develop, main]
concurrency:
group: ci-${{ github.ref }}-group
cancel-in-progress: true
jobs:
default:
runs-on: ubuntu-latest
# Service containers to run with `container-job`
services:
# Label used to access the service container
postgres:
# Docker Hub image
image: postgres
# Provide the password for postgres
env:
POSTGRES_PASSWORD: sa123456
POSTGRES_USER: learning
POSTGRES_DB: school_management
# Set health checks to wait until postgres has started
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
# override spring.datasource.url
- name: Setup config
run: |
mkdir config
echo 'spring.datasource.url=jdbc:postgresql://postgres:5432/school_management' > config/application.properties
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Update dependency graph
uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6
- name: Build Jar file
run: ./project-dev build-jar
- name: Save Jar file
uses: actions/upload-artifact@v3
with:
name: demo-0.0.1-SNAPSHOT
path: target/demo-0.0.1-SNAPSHOT.jar
retention-days: 1
Another possibility is to use an embedded database like H2 for tests.
With this, you don't have to setup any database.
答案2
得分: 1
"Looking at your logs line 1351
org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
Your tests are trying to connect to a local Postgres instance that is not available. Also looking at your tests you have both unit and integration tests. Whereas an integration test needs to load the application context meaning that your running application inside of the pipeline will not be able to connect to Postgres. Hence, all of your integration tests will fail that utilize Postgres.
However, your other tests are passing, line 2085:
2023-02-14 12:13:39.378 INFO 1740 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url='jdbc:h2:mem:d00124ab-b172-4fd1-bf29-b4836ae2f938;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
these are working since your application is connecting correctly to the h2
database that you have.
the StudentRepositoryTest
are working since you have the following annotation in your class @DataJpaTest
which will boot up this integration test and connect to the in-memory database.
I think the test that is failing is the following DemoApplicationTests
:
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
}
}
Since this test load the application context (the whole application) and will automatically try to connect with postgres.
So to fix the issue just delete the file. or a better solution which I would recommend (which is a bit more advanced) is to use something called testcontainers
and actually run a postgres database inside of a container.
The reason why am suggesting the latter solution is normally once you want to run an integration test you try to have the exact solution that your application runs on production. Hence, an h2
database might have edge cases that does not match postgres database"
英文:
Looking at your logs line 1351
org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
Your tests are trying to connect to a local Postgres instance that is not available. Also looking at your tests you have both unit and integration tests. Whereas an integration test needs to load the application context meaning that your running application inside of the pipeline will not be able to connect to Postgres. Hence, all of your integration tests will fail that utilize Postgres.
However, your other tests are passing, line 2085:
2023-02-14 12:13:39.378 INFO 1740 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url='jdbc:h2:mem:d00124ab-b172-4fd1-bf29-b4836ae2f938;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'
these are working since your application is connecting correctly to the h2
database that you have.
the StudentRepositoryTest
are working since you have the following annotation in your class @DataJpaTest
which will boot up this integration test and connect to the in-memory database.
I think the test that is failing is the following DemoApplicationTests
:
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
}
}
Since this test load the application context (the whole application) and will automatically try to connect with postgres.
So to fix the issue just delete the file. or a better solution which I would recommend (which is a bit more advanced) is to use something called testcontainers
and actually run a postgres database inside of a container.
The reason why am suggesting the latter solution is normally once you want to run an integration test you try to have the exact solution that your application runs on production. Hence, an h2
database might have edge cases that does not match postgres database
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论