Search code examples
javajunitcontinuous-integrationgithub-actions

How to run Spring boot app's unit test on GitHub Action


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?


Solution

  • 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.