0

I'm trying to do a test suite to check a @oneToMany relation i have

I have a book_category and a book but my issue is that i have several small tests inside a test class and it seems that the db (H2) is being deleted after each test

here is my code

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

    }

I get a null pointer when the code in test number 2 (createBookWithCategory) tries to fetch the category previously inserted in test 1

I tought that adding the @Transactional annotation would help persists the data until the entire test suite ends but its not working

here are my 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 Answers 3

5

Tests annotated with @DataJpaTest are already @Transactional so adding @Transactional explicitly will, as you have observed, have no effect.

The behaviour that you are seeing is because, by default, the test framework rolls back the transaction at the end of each test. This is to avoid changes made to the database in one test affecting the behavior of another test. This is generally recommended as it allows your tests to execute in any order.

In your case, you have ordered the tests and you want the changes made in one test to affect a subsequent test. You can instruct the test framework to commit a test method's transaction by annotating the method with @Commit. Alternatively, if you want every test in a class to commit its transaction you can annotate the class with @Commit instead.

You can learn more about this in the reference documentation for @Commit, @Rollback, and transaction rollback and commit behavior.

Sign up to request clarification or add additional context in comments.

2 Comments

It's not working, i annotated each method that does a db change with the @commit annotation and it still fails
Perhaps you can update your question showing the changes that you've made? The logs from when you run the tests would also be useful.
0

Spring Integration tests by default roll back transactions after each test. (https://docs.spring.io/spring/docs/3.0.0.M4/reference/html/ch09s03.html#testing-tx)

You can annotate the tests that you don't want to their changes rolled back with either @Rollback(false) or @Commit

Comments

0

H2 Database will delete everything after the last connection has been closed. If you want to circumvent that behaviour you have to add

;DB_CLOSE_DELAY=-1

After your database configuration, for example:

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

I do NOT recommend this approach, tests that are dependent on other tests are BAD PRACTICE. Every test should clear the db, set up its own expectations then run tests.

You have been warned.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.