@DataJpaTest 让repository层面的测试更加简洁
package pojo; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; @Entity @Table(name = "product") public class Product { @Id @Column(name = "id") int id; @Column(name = "name") String type; @Column(name = "type") String name; @Column(name = "prtdesc") String prtdesc; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPrtdesc() { return prtdesc; } public void setPrtdesc(String prtdesc) { this.prtdesc = prtdesc; } } |
package repository; import org.springframework.data.jpa.repository.JpaRepository; import pojo.Product; public interface ProductRepository extends JpaRepository public Page findAll(Specification spec, Pageable pageable); } |
@DataJpaTest 执行完test是事务回滚的。我想要数据保存下来就加入了@Transactional(propagation = Propagation.SUPPORTS)
如果不定义@ContextConfiguration(classes = StdCfg.class), 则默认是整个应用环境,会加载controller, service类,比较麻烦。使用这个标签后,就是单纯的repository层面的bean,简单快捷
package repository; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.core.annotation.Order; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.test.context.ContextConfiguration; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import pojo.Product; @Transactional(propagation = Propagation.SUPPORTS) @ContextConfiguration(classes = StdCfg.class) @DataJpaTest @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public class ProductRepositoryTest { @Autowired ProductRepository repo; @Order(1) @Test void testfind() { Product car=new Product(); car.setId(3); car.setType("toy"); car.setName("gun"); car.setPrtdesc("water gun"); repo.save(car); Product plane=new Product(); plane.setId(4); plane.setType("toy"); plane.setName("boat"); plane.setPrtdesc("air boat"); repo.save(plane); Product std=repo.findById(1).get(); assertEquals(car.getPrtdesc(), std.getPrtdesc() ); } @Order(2) @Test void testPage() { int start=1; int size=2; Sort sort = Sort.by(Sort.Direction.ASC, "id"); Pageable pageable = PageRequest.of(start, size, sort); Page page=repo.findAll(pageable); System.out.println(page.getSize()+"; "+page.getTotalPages()); List list.forEach(a->System.out.println(a.getPrtdesc())); } @Order(3) @Test //test search with Pageable void testPageSpecification() { int start = 1; int size = 2; Sort sort = Sort.by(Sort.Direction.ASC, "id"); Pageable pageable = PageRequest.of(start, size, sort); Page page = repo.findAll(getSpecification("toy"), pageable); List list.forEach(a -> { System.out.println("specification:"+a.getPrtdesc()); }); } public Specification getSpecification(String type) { return new Specification() { @Override public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { Predicate predicate = criteriaBuilder.equal(root.get("type"), type); return predicate; } }; } void add() { Product car=new Product(); car.setId(1); car.setType("toy"); car.setName("car"); car.setPrtdesc("mobile car"); repo.save(car); Product plane=new Product(); plane.setId(2); plane.setType("toy"); plane.setName("plane"); plane.setPrtdesc("model plane"); repo.save(plane); } } |
当Repository用的是类而不是interface时,我的测试中需要使用@ComponentScan,否则就不能识别,所以我使用了@ComponentScan("repository")
如果不定义@TestPropertySource("classpath:application-mysql.properties"),好像加载不了
package repository; import javax.sql.DataSource; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.test.context.TestPropertySource; @TestPropertySource("classpath:application-mysql.properties") @EnableJpaRepositories("repository") @ComponentScan("repository") @EntityScan("pojo") @Configuration public class StdCfg { @Bean @ConfigurationProperties(prefix = "spring.datasource") // 读取配置文件中的属性 public DataSource dataSource() { return DataSourceBuilder.create().build(); } } |
为了好玩,配置了多个数据库
spring.datasource.jdbc-url=jdbc:mysql://localhost:3306/blue?serverTimezone=UTC #spring.datasource.url = jdbc:mysql://localhost:3306/blue?serverTimezone=UTC spring.datasource.username = root spring.datasource.password = root spring.datasource.driverClassName = com.mysql.jdbc.Driver red.datasource.jdbc-url = jdbc:mysql://localhost:3306/red?serverTimezone=UTC #red.datasource.url = jdbc:mysql://localhost:3306/red?serverTimezone=UTC red.datasource.username = root red.datasource.password = root red.datasource.driverClassName = com.mysql.jdbc.Driver #----------------------JPA------------------------------ # Specify the DBMS spring.jpa.database = MYSQL # Show or not log for each sql query spring.jpa.show-sql = true # Hibernate ddl auto (create, create-drop, update) spring.jpa.hibernate.ddl-auto = update # Naming strategy ##spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.DefaultNamingStrategy spring.jpa.generate-ddl=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect |