简体   繁体   中英

Spring Boot / Spring Data integration tests

Didn't manage to configure Spring Boot for integration testing. Cold you please take a look at the code below:

Entities

@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

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

Test configuration

@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;
    }

}

Application properties

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

Test case

@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);
    }
}

I tried a different configuration (its last edition), but all the time I get the same exception:

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]

More over the nature of the exception is strange as the main idea to let spring boot to auto-generate schema according to entity annotations. Thus, at the moment of insertion spring had to create table but looks that it didn't. If someone give an idea what I did wrong or if somebody already faced such an issue - please let me knkow. Thanks.

Either use @SpringBootTest (full loaded context) or use @DataJpaTest (JPA context).

From the documentation :

Annotation that can be used in combination with @RunWith(SpringRunner.class) for a typical JPA test. Can be used when a test focuses only on JPA components.

...

If you are looking to load your full application configuration, but use an embedded database, you should consider @SpringBootTest combined with @AutoConfigureTestDatabase rather than this annotation.

Besides, by specifying DaoTestConfiguration as configuration class in your test class :

@SpringBootTest(classes = DaoTestConfiguration.class)

you don't rely on default values for embedded database provided Spring boot as in DaoTestConfiguration , you declared the 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;
}

Either don't create this datasource and let Spring Boot do the job to create it or else specify also the property spring.jpa.hibernate.ddl-auto in the datasource bean declaration.

在application.properties中添加此属性

spring.jpa.hibernate.ddl-auto=update

If you want to do a @DataJpaTest, my answer is similar to Bhusan Umiyal, but use create instead of update .

spring.jpa.hibernate.ddl-auto=create

And like everyone else in here has said, don't use it along with @SpringBootTest .

Also make sure that your test classes are in the same or sub package with the main Spring Boot application class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM