I am trying to connect to Postgres database instance of TestContainers but I get the error org.postgresql.util.PSQLException: ERROR: relation "proposal" does not exist
in Spring data repository class "ProposalRepository" when running the "HelloRestControllerTest"
The flyway is enabled in the config.
I created a demo project with just the basic stuff.
HelloRestController:
import com.example.demo.entity.Proposal
import com.example.demo.repo.ProposalRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.repository.findByIdOrNull
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class HelloRestController @Autowired constructor(val proposalRepository: ProposalRepository) {
@GetMapping("/hello")
fun hello(): ResponseEntity<Proposal>{
val result = proposalRepository.findByIdOrNull("123") //error is thrown here.
return ResponseEntity.ok(result)
}
}
ProposalRepository:
import com.example.demo.entity.Proposal
import org.springframework.data.repository.CrudRepository
interface ProposalRepository : CrudRepository<Proposal, String>
Entity:
import java.math.BigDecimal
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Table
import javax.persistence.Id
@Entity
@Table(name = "proposal")
data class Proposal(
@Id
@Column(name = "proposal_id")
val proposalId: String,
@Column(name = "amount", nullable = true)
val amount: BigDecimal?,
@Column(name = "user_id")
val userId: String? = null
)
Flyway SQL script:
create table proposal (
proposal_id varchar(50),
amount decimal not null ,
user_id varchar(35)
);
application-it-test.yml in src/test/resources folder:
spring:
datasource:
#driver-class-name: org.postgresql.Driver
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:tc:postgresql:11.6:///databasename
hikari:
max-lifetime: 500000
connection-timeout: 300000
idle-timeout: 600000
maximum-pool-size: 5
minimum-idle: 1
flyway:
enabled: true
url: ${spring.datasource.url}
locations: 'classpath:db/migration/postgresql'
table: FLY_VERSION
jpa:
show-sql: true
database-platform: org.hibernate.dialect.PostgreSQLDialect
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<kotlin.version>1.6.21</kotlin.version>
<spring-cloud.version>2021.0.3</spring-cloud.version>
<testcontainers.version>1.17.3</testcontainers.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
<exclusions>
<!-- excluded because REST assured 4.3.0+ expects Groovy 3+ (https://github.com/rest-assured/rest-assured/issues/1283) -->
<exclusion>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
<exclusions>
<!-- excluded because REST assured 4.3.0+ expects Groovy 3+ (https://github.com/rest-assured/rest-assured/issues/1283) -->
<exclusion>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
</exclusion>
<!-- excluded because REST assured 4.3.0+ expects Groovy 3+ (https://github.com/rest-assured/rest-assured/issues/1283) -->
<exclusion>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-xml</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-bom</artifactId>
<version>${testcontainers.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
<plugin>jpa</plugin>
</compilerPlugins>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-noarg</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
HelloRestControllerTest:
import io.restassured.RestAssured.given
import io.restassured.http.ContentType
import org.junit.jupiter.api.Test
import org.junit.runner.RunWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.web.server.LocalServerPort
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.springframework.test.context.junit4.SpringRunner
import org.testcontainers.containers.PostgreSQLContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("it-test")
@AutoConfigureWireMock(port = 1234)
@RunWith(SpringRunner::class)
@Testcontainers
class HelloRestControllerTest {
@LocalServerPort
final val portNumber = 0
val baseUrl = "http://localhost:$portNumber"
companion object {
@Container
var postgreSQL: PostgreSQLContainer<*> = PostgreSQLContainer("postgres:11.6")
@DynamicPropertySource
fun postgreSQLProperties(registry: DynamicPropertyRegistry) {
registry.add("spring.datasource.username") { postgreSQL.username }
registry.add("spring.datasource.password") { postgreSQL.password }
}
}
@Test
fun test() {
val helloResponse = given()
.contentType(ContentType.JSON)
.get("$baseUrl$portNumber/hello")
.andReturn()
println(helloResponse.body)
}
}
The code and configuration looks fine so I am not able to figure out what is the problem. What could be the issue here?
EDIT:
If I add @Sql
annotation in HelloRestControllerTest
as shown below, I do not see any error. It looks like Flyway is not able to run the scripts to the right database or something. Not sure why?
@Sql(scripts = ["classpath:/db/migration/postgresql/V01__PROPOSAL.sql"])