I want to run tests on my app using h2 as a database but every time I attempt to run a test it shows me an exception saying that h2 db is empty. None of the related questions I`ve read helped me.
This is the method I am trying to test:
/// I know is pointless to test this, but I am learning to implement tests
public interface ConocimientoRepository extends JpaRepository<Conocimiento,Long>{
@Modifying
@Transactional
@Query(value = "DELETE FROM conocimiento WHERE busca_id = :buscaId", nativeQuery = true)
void deleteAllConocimientoFromBuscaId(@Param("buscaId") Long buscaId);
}
The test itself:
@DataJpaTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
@ActiveProfiles("test")
public class ConocimientoRepositoryTests {
@Autowired
BuscaRepository buscaRepository;
@Autowired
ConocimientoRepository conocimientoRepository;
private Busca b1, b2;
private List<Conocimiento> listConocimientos;
@BeforeEach
public void initData() {
b1 = new Busca("Ana", "[email protected]", "Sevilla", "612345678", "Password1!");
b2 = new Busca("Luis", "[email protected]", "Madrid", "712345678", "SecurePwd2@");
listConocimientos = List.of(
Conocimiento.builder()
.centroEducativo("Centro 1")
.titulo("Título 1")
.inicioPeriodoConocimiento(LocalDate.of(2020, 1, 1))
.finPeriodoConocimiento(LocalDate.of(2021, 1, 1))
.busca(b1)
.build(),
Conocimiento.builder()
.centroEducativo("Centro 2")
.titulo("Título 2")
.inicioPeriodoConocimiento(LocalDate.of(2019, 1, 1))
.finPeriodoConocimiento(LocalDate.of(2020, 1, 1))
.busca(b1)
.build(),
Conocimiento.builder()
.centroEducativo("Centro 3")
.titulo("Título 3")
.inicioPeriodoConocimiento(LocalDate.of(2018, 1, 1))
.finPeriodoConocimiento(LocalDate.of(2019, 1, 1))
.busca(b2)
.build()
);
b1.setListaConocimientos(listConocimientos.subList(0, 1));
b2.setListaConocimientos(List.of(listConocimientos.get(2)));
buscaRepository.saveAll(List.of(b1,b2));
}
@Test
public void ConocimientoRepository_DeleteAllConocimientoFromBuscaId_RemoveAllConocimientoFromBuscaId() {
buscaRepository.delete(b1);
Assertions.assertThat(listConocimientos.stream().allMatch(con -> con.getBusca().getId() != b1.getId()));
}
}
Entities affected by test:
@EqualsAndHashCode(of = "id")
@Data
@ToString(exclude = "busca")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Conocimiento {
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Long id;
@NotNull
@Size(max = 40, message = "Máximo 40 carácteres")
private String centroEducativo;
@NotNull
@Size(max = 40, message = "Máximo 40 carácteres")
private String titulo;
@NotNull
private LocalDate inicioPeriodoConocimiento;
@NotNull
private LocalDate finPeriodoConocimiento;
@ManyToOne
@JoinColumn(name = "busca_id")
@JsonBackReference(value = "busca-conocimiento")
private Busca busca;
public Conocimiento(@NotNull @Size(max = 40, message = "Máximo 40 carácteres") String centroEducativo,
@NotNull @Size(max = 40, message = "Máximo 40 carácteres") String titulo, LocalDate fechaInicio, LocalDate fechaFin) {
this.centroEducativo = centroEducativo;
this.titulo = titulo;
this.inicioPeriodoConocimiento = fechaInicio;
this.finPeriodoConocimiento = fechaFin;
}
}
@Data
@ToString(exclude = {"listaOfertas"})
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id")
@Builder
@Entity
@Table(name = "Busca")
public class Busca extends Usuario {
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "busca")
private List<Experiencia> listaExperiencias;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "busca")
private List<Conocimiento> listaConocimientos;
@JsonBackReference("busca-oferta")
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "busca_oferta", joinColumns = @JoinColumn(name = "busca_id"), inverseJoinColumns = @JoinColumn(name = "oferta_id"))
@JsonIgnoreProperties("busca_id")
private List<Oferta> listaOfertas;
public Busca(String nombre, String email, String ciudad, String telefono, String password) {
super(nombre, email, ciudad, telefono, password, Rol.BUSCA);
}
}
This is the content of application-test.properties:
spring.h2.console.enabled=true
spring.sql.init.platform=h2
spring.jpa.defer-datasource-initialization=true
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create-drop
And finally, the stack error from the test:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement [Table "BUSCA" not found (this database is empty); SQL statement:
insert into busca (ciudad,email,nombre,password,rol,telefono) values (?,?,?,?,?,?) [42104-214]] [insert into busca (ciudad,email,nombre,password,rol,telefono) values (?,?,?,?,?,?)]; SQL [insert into busca (ciudad,email,nombre,password,rol,telefono) values (?,?,?,?,?,?)]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:277)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:241)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:550)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:335)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:164)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:220)
at jdk.proxy2/jdk.proxy2.$Proxy142.saveAll(Unknown Source)
at com.example.demo.repositories.ConocimientoRepositoryTests.initData(ConocimientoRepositoryTests.java:67)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
What could it be?
EDIT: Reopened issue because the question used to mark this problem as duplicated has a solution that I ALREADY TRIED. The question that I was redirected states that to fix the issue all I have to do is set this on my application-test.properties:
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
Which I already did:
spring.h2.console.enabled=true
spring.sql.init.platform=h2
spring.jpa.defer-datasource-initialization=true
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create-drop