Spring Boot / Spring数据集成测试

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot / Spring数据集成测试相关的知识,希望对你有一定的参考价值。

没有设法配置Spring Boot进行集成测试。冷你请看看下面的代码:

实体

@Entity(name = "Item")
@Table(name = "item")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Getter @Setter @NoArgsConstructor
public class Item extends CoreEntity {

    @Embedded
    protected CurrencyAmount amount;

    @Column(name = "operation_time")
    protected ZonedDateTime operationTime;

    @Column(name = "description")
    protected String description;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "category_id")
    protected ItemCategory category;

}



@Entity(name = "Income")
@Table(name = "income")
@Getter @Setter @NoArgsConstructor
public class Income extends Item {

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "budget_id")
    private Budget budget;

    ...

}

知识库

@Repository("incomeDao")
public interface IncomeDao extends JpaRepository<Income, Long> {
}

测试配置

@Configuration
@EnableJpaRepositories(basePackages = "dao.item")
@EntityScan(basePackages = {"model"})
@PropertySource("classpath:application.properties")
@EnableTransactionManagement
public class DaoTestConfiguration {

    @Autowired
    private Environment environment;

    public DataSource getDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getProperty("spring.datasource.driver-class-name"));
        dataSource.setUrl(environment.getProperty("spring.datasource.url"));
        dataSource.setUsername(environment.getProperty("spring.datasource.username"));
        dataSource.setPassword(environment.getProperty("spring.datasource.password"));
        return dataSource;
    }

}

应用属性

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

测试用例

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DaoTestConfiguration.class)
@DataJpaTest
public class IncomeDaoTest {

    @Autowired
    private IncomeDao incomeDao;

    @Test
    public void testSave() {
        Budget budget = Budget.getBulider().setMonth(Month.NOVEMBER).build();
        ItemCategory category = ItemCategory.getBuilder()
                .setItemGroup(ItemGroup.INCOME)
                .setCathegoryName("Salary")
                .build();
        Income income = Income.getBuilder()
                .setBudget(budget)
                .setCurrencyAmount(new CurrencyAmount(Currency.getInstance("USD"), BigDecimal.TEN))
                .setDescription("Monthly salary")
                .setItemCategory(category)
                .setOperationTime(ZonedDateTime.of(2017, 1, 12, 12, 0, 0, 0, ZoneId.of("UTC")))
                .build();
        incomeDao.save(income);

        assertThat(incomeDao.findAll()).containsExactly(income);
    }
}

我尝试了不同的配置(上一版),但是我一直得到同样的例外:

Caused by: org.h2.jdbc.JdbcSQLException: Таблица "INCOME" не найдена
Table "INCOME" not found; SQL statement:
insert into income (model/amount, currency, category_id, description, operation_time, budget_id, id) values (?, ?, ?, ?, ?, ?, ?) [42102-196]

更多关于异常的本质是奇怪的,因为让spring引导根据实体注释自动生成模式。因此,在插入时,弹簧必须创建表,但看起来它没有。如果有人知道我做错了什么,或者有人已经遇到过这样的问题 - 请让我知道。谢谢。

答案

使用@SpringBootTest(满载上下文)或使用@DataJpaTest(JPA上下文)。

来自documentation

可以与@RunWith(SpringRunner.class)结合使用的注释,用于典型的JPA测试。当测试仅关注JPA组件时可以使用。

...

如果您要加载完整的应用程序配置,但使用嵌入式数据库,则应考虑将@SpringBootTest与@AutoConfigureTestDatabase结合使用而不是此注释。

此外,通过在测试类中将DaoTestConfiguration指定为配置类:

@SpringBootTest(classes = DaoTestConfiguration.class)

你不依赖于嵌入式数据库提供的Spring引导的默认值,就像在DaoTestConfiguration中一样,你声明了bean:

public DataSource getDataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(environment.getProperty("spring.datasource.driver-class-name"));
    dataSource.setUrl(environment.getProperty("spring.datasource.url"));
    dataSource.setUsername(environment.getProperty("spring.datasource.username"));
    dataSource.setPassword(environment.getProperty("spring.datasource.password"));
    return dataSource;
}

要么不创建此数据源,要让Spring Boot完成创建它的工作,或者在数据源bean声明中指定属性spring.jpa.hibernate.ddl-auto

另一答案

在application.properties中添加此属性

spring.jpa.hibernate.ddl-auto=update
另一答案

如果你想做一个@DataJpaTest,我的回答类似于Bhusan Umiyal,但是使用create而不是update

spring.jpa.hibernate.ddl-auto=create

就像这里的其他人都说的那样,不要和@SpringBootTest一起使用它。

还要确保您的测试类与主Spring Boot应用程序类位于相同或子包中。

以上是关于Spring Boot / Spring数据集成测试的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 2.X:Spring Boot 集成 Redis

Spring-boot集成pgmongo多数据源

Spring-boot集成pgmongo多数据源

Spring boot Mybatis-Plus数据库单测实战(三种方式)

spring boot集成redis基础入门

spring boot集成mybatis+事务控制