Conteúdo do item:
Vamos começar a corrigir bugs que estão relacionados ao banco de dados
No pom.xml precisamos das seguintes dependências:
<!-- Junit5 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Junit H2 memory database -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
Vamos criar o arquivo application.properties na pasta de teste "src/test/resources", e vamos adicionar as seguintes propriedades:
# Datasource connection properties
spring.sql.init.platform=h2
spring.jpa.defer-datasource-initialization=true
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=LEGACY;NON_KEYWORDS=USER
# Hibernate Configuration Properties
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
Como o properties está na pasta de teste, o banco de dados H2 será acionado durante o ciclo de teste da aplicação
Essa propriedade nos dará a opção de criar o arquiivo data-h2.sql, onde o script será acionado durante os testes
spring.sql.init.platform=h2
Com essa opção, ele deixará o JPA criar as tabelas somente depois disso vai chamar o script data-h2.sql para fazer os inserts.
spring.jpa.defer-datasource-initialization=true
Configuração para rodar o driver do H2
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
Nesse aqui o mais importante é:
- NON_KEYWORDS=USER. Tenho uma tabela usando o nome "user" e isso é uma palavra privada e para resolver esse problema coloquei a opção
- MODE=MYSQL. Ativa a compatibilidade com o Mysql
- CLOSE_ON_EXIT e DB_CLOSE_DELAY. Manter a base ligada até o fim dos testes
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL;NON_KEYWORDS=USER
Alterações que tiver que fazer no meu projeto:
ERRO:
Caused by: org.h2.jdbc.JdbcSQLFeatureNotSupportedException: Feature not supported: "NUMERIC(19, 2)"; SQL statement:
Solução:
Para arrumar o erro no mapeamento dos BigInteger eu coloquei a propriedade columnDefinition = "BIGINT" em todos os lugares que tinham BigInteger
import javax.persistence.Column;
Colocar columnDefinition = "BIGINT" para esse tipo de variável
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "blog_id", columnDefinition = "BIGINT")
private BigInteger id;
ERRO:
Caused by: org.h2.jdbc.JdbcSQLDataException: Value too long for column "CONTENT CHARACTER VARYING(255)
Solução:
Para resolver o problema de campo muito longo, eu coloquei a anotação @Lob
import javax.persistence.Lob;
Colocar em cima da variável String com grande conteúdo
@Column(name = "content")
@Lob
private String content;
Inserts
Próximo passo foi criar o arquivo data-h2.sql dentro da pasta "src\test\resources", nele eu coloquei todos os inserts que precisava. Como as tabelas estavam relacionadas eu tive que colocar logo no começo do arquivo um comando para desativar os relacionamentos:
SET REFERENTIAL_INTEGRITY FALSE;
Na sequência eu exportei todos os inserts através da ferramenta Mysql Workbench e coloquei dentro do arquivo
Gerando Inserts
Vamos utilizar a ferramenta do MYSQL para realizar a exportação dos dados para que possamos inserir dentro do H2. Veja no vídeo.
Classe de teste
Como ficou minha classe de teste
package br.com.byiorio.api.product;
import java.math.BigInteger;
import javax.servlet.http.Cookie;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import br.com.byiorio.api.ByiorioApiApplication;
import br.com.byiorio.api.infra.security.JWTManager;
import br.com.byiorio.api.user.UserEntity;
@SpringBootTest(classes = ByiorioApiApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class ProductChapterPrivControllerTest {
@Autowired
private MockMvc mvc;
@Autowired
JWTManager jwtManager;
UserEntity admin;
@BeforeEach
public void setup() {
// Criando usuario com permissao de admin
admin = new UserEntity();
admin.setId(BigInteger.valueOf(2));
admin.setPerfil(BigInteger.valueOf(2));
}
@Test
public void sucessoVazioTest() throws Exception {
// chama o endpoint
mvc.perform(MockMvcRequestBuilders
.get("/priv/v1/product/1")
.cookie(new Cookie(HttpHeaders.AUTHORIZATION,
JWTManager.TOKEN_PREFIX.concat(jwtManager.createUserJWT(admin))))
.accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isNoContent());
}
@Test
public void sucessoConteudoTest() throws Exception {
// chama o endpoint
mvc.perform(MockMvcRequestBuilders
.get("/priv/v1/product/2")
.cookie(new Cookie(HttpHeaders.AUTHORIZATION,
JWTManager.TOKEN_PREFIX.concat(jwtManager.createUserJWT(admin))))
.accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(jsonPath("$.erros[*][?(@.origem =='valorTotalFinanciamento')][?(@.mensagem =='must not be null')]").exists())
.andExpect(jsonPath("$.erros[*][?(@.origem =='statusSimulacao')][?(@.mensagem =='must not be blank')]").exists());
}
}
junit5; java; teste; h2; sonarqube; bug; correção