如何在GitHub Action上运行Spring Boot应用的单元测试

huangapple go评论68阅读模式
英文:

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 under localhost: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 to jdbc: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

huangapple
  • 本文由 发表于 2023年2月14日 20:45:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75448037.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定