内存db数据中的Spring Boot测试在测试之间不持久

时间:2019-05-25 10:44:05

标签: spring-boot junit

我正试图做一个测试套件来检查我拥有的@oneToMany关系

我有一本book_category和一本书 但是我的问题是,我在一个测试类中有几个小型测试,而且每次测试后似乎都删除了数据库(H2)

这是我的代码

@Slf4j
@RunWith(SpringRunner.class)
@DataJpaTest
@TestPropertySource(locations="classpath:test.properties")
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class BookServiceTest {

    @Autowired
    private BookService bookService;

    @Autowired
    private BookCategoryService categoryService;

    @Test
    @Order(1) 
    public void insertBookCategories() {
        BookCategory cat1 = new BookCategory();
        cat1.setCategoryCode(32);
        cat1.setCategoryName("Category 1");
        BookCategory cat2 = new BookCategory();
        cat2.setCategoryCode(323);
        cat2.setCategoryName("Category 2");
        categoryService.save(cat1);
        categoryService.save(cat2);
        List<BookCategory> categories = categoryService.findAll();
        assertEquals(2, categories.size());
        log.debug("Executed test number 1");
    }

    @Test
    @Order(2) 
    public void createBookWithCategory() {
        Book book = new Book();
        book.setDescription("Test Book");
        book.setNumberOfSales(5);
        book.setTitle("Test title");
        BookCategory cat = categoryService.findByCategoryName("Category 2");
        assertNotNull(cat); <------- this fails!!!!
        assertEquals("Category 2", cat.getCategoryName());
        book.setCategory(cat);
        bookService.save(book);
        log.debug("Executed test number 2");
    }

    @Test
    @Order(3)
    public void deleteCategoryWithBook() {
        BookCategory cat = categoryService.findByCategoryName("Category 2");
        assertEquals("Category 2", cat.getCategoryName());
        categoryService.delete(cat);
        log.debug("Executed test number 3");

    }

    @Test
    @Order(4)
    public void assertBookIsNotNull() {
        Book book = bookService.findByTitle("Test title");
        assertEquals("Test Book", book.getDescription());
        assertNull(book.getCategory());
        log.debug("Executed test number 4");

    }

当测试编号2(createBookWithCategory)中的代码试图获取先前插入到测试1中的类别时,我得到一个空指针

我坚信添加@Transactional批注将有助于将数据持久化,直到整个测试套件结束但不起作用

这是我的test.properties

h2.datasource.url=jdbc:h2:mem:somedatebase;DB_CLOSE_DELAY=-1
h2.datasource.username=sa
h2.datasource.password=
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.hbm2ddl.auto=create

3 个答案:

答案 0 :(得分:3)

@DataJpaTest注释的测试已经@Transactional,因此,如您所见,显式添加@Transactional无效。

您看到的行为是因为,默认情况下,测试框架会在每次测试结束时回滚事务。这是为了避免在一个测试中对数据库所做的更改影响另一个测试的行为。通常建议这样做,因为它可以使您的测试以任何顺序执行。

在您的情况下,您已经订购了测试,并且希望对一个测试进行的更改会影响后续测试。您可以通过用@Commit注释测试方法来指示测试框架提交测试方法的事务。另外,如果您希望类中的每个测试都提交其事务,则可以改用@Commit对该类进行注释。

您可以在参考文档中找到有关@Commit@Rollbacktransaction rollback and commit behavior的更多信息。

答案 1 :(得分:0)

Spring Integration测试默认在每次测试后回滚事务。 (https://docs.spring.io/spring/docs/3.0.0.M4/reference/html/ch09s03.html#testing-tx

您可以使用@Rollback(false)@Commit批注您不希望其更改回滚的测试

答案 2 :(得分:0)

在关闭最后一个连接后,H2数据库将删除所有内容。如果您想规避该行为,则必须添加

; DB_CLOSE_DELAY = -1

配置数据库后,例如:

jdbc:h2:mem:test; DB_CLOSE_DELAY = -1

我不推荐这种方法,因为依赖于其他测试的测试是不良实践。每个测试都应清除数据库,设置自己的期望,然后运行测试。

您已收到警告。