skip to Main Content

I have a standard spring boot application with this docker file:

FROM maven:latest AS maven

WORKDIR /usr/src/app
COPY . /usr/src/app
# Compile and package the application to an executable JAR
RUN mvn package

FROM amazoncorretto:17-alpine-jdk

ARG JAR_FILE=app.jar

WORKDIR /opt/app

# Copy the jar from the maven stage to the /opt/app directory of the current stage.
COPY --from=maven /usr/src/app/target/${JAR_FILE} /opt/app/

EXPOSE 8080

ENTRYPOINT ["java","-jar","app.jar"]

My application.properties file has the connection spring to my postgres db running in a docker container:

# datasource
spring.datasource.url=jdbc:postgresql://db:5432/myApp?currentSchema=gpclinic&createDatabaseIfNotExist=true
spring.datasource.username=uname
spring.datasource.password=pword

When I run:

docker build -t myApp .

I get a failure as the unit tests fail because the DB container is not running.

Will I need a Postgres container running to pass my tests? Or what is the best way to get around this?

4

Answers


  1. As I understand you need insert endpoint of postgres where db in jdbc:postgresql://db:5432
    Or if you have docker-compose.yml, service name of postgresql should be db

    Login or Signup to reply.
  2. Skip tests while building the image, see Maven package/install without test (skip tests)

    Once the image is built, you can run the tests by starting a container in an environment where a DB endpoint is available.

    Login or Signup to reply.
  3. Roughly speaking, when you build your image under the hood docker creates a series of intermediate containers, one for every line in your Dockerfile.

    You are trying to connect from one of this intermediate containers, the one which is packaging your application, to another container running Postgres in your host.

    I am not sure if it will work – the subject had been broadly covered here in SO – but, if you are using MacOS or Windows, and your Postgres container exposes the port to the host, you could try modifying the connection string in your Spring properties and use the network address host.docker.internal to try reaching the database:

    # datasource
    spring.datasource.url=jdbc:postgresql://host.docker.internal:5432/myApp?currentSchema=gpclinic&createDatabaseIfNotExist=true
    spring.datasource.username=uname
    spring.datasource.password=pword
    

    You mentioned compose as well, but again I am not sure whether it is possible. Please, see this related SO question.

    Having said that, please, be aware that the solution has different drawbacks, among others:

    • It makes your docker build not portable, think about building it in Linux or in a CI/CD system.
    • Probably you will need to set some kind of Spring profile or similar stuff for dealing with the properties value change.

    I think that, as suggested in other answers, it is preferable to skip the unit tests execution while building your image. You can achieve this in several ways, for example (clean is not necessary, but I usually clean before packaging the application):

    # Compile and package the application to an executable JAR
    RUN mvn clean package -skipTests
    

    Or:

    # Compile and package the application to an executable JAR
    RUN mvn clean package -Dmaven.test.skip=true
    

    The same approach is addressed in this SO related question, for instance.

    Following this approach, if you really need to run your tests, it is preferable to use a devoted step in a CI/CD system pipeline, for example, instead of running it in the docker build.

    Finally, please, consider why you are accessing a database in a unit test: in my opinion, and please, forgive me, because SO answer shouldn’t be opinion based, it is something that you can find in an integration test, for example, but I think it is not commonly used in unit tests.

    Even in the case that using a database is a must, for simplicity, predictability, in order to improve portability and build isolation, please, consider use an in-memory one like H2 with the necessary information, and run your tests against it instead.

    Login or Signup to reply.
  4. I think the Below Answer might Help you

    May be You can Add h2 database properites in a seperate properties file

    application-test.properties.

    spring.datasource.url=jdbc:h2:mem:testdb
    spring.datasource.driverClassName=org.h2.Driver
    spring.datasource.username=user
    spring.datasource.password=password
    spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
    

    And may be Change the Scope in original application.properties

    spring.profiles.active=test
    

    And you can Third Dependency for h2 Database as it will not be dependent on any other Database ..h2 Database runs in your JVM

    <!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>test</scope>
    </dependency>
    

    So in this Case you Dont need any container to Run the Tests…Once the Tests Passes your package will be built.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search