Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate @Formula not working in Spring boot Tests when using @DataJpaTest

I'm trying to write an integration test for a java spring project. At some point in the code I need to check customer.getId(), where the ID is created by a @Formula annotation like this: (keep in mind Customer_Id is my auto-incrementing primary key)

@Formula("Customer_Id")
private int id

I use lombok to generate getters and setters methods. My database for testing is H2 and I use Junit5 for my tests. The problem i'm facing is that i cannot test the getId() behavior because it's always 0 when I annotate the tests with @DataJpaTest. I made it work with @SpringBootTest but I would like to stick to sliced tests.

Is there a way to make @DataJpaTest work with @Formulas ?

Thanks in advance.

@Entity(name="customers")
@Table(name="Customers")
@Getter
@Setter
@NoArgsConstructor
public class Customer{

    @Formula("Customer_Id")
    private int id;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="Customer_Id", unique=true, nullable=false, precision=10)
    private int customerId;
}
// if it is annotated with @SpringBootTest the tests passes
@DataJpaTest
@ActiveProfiles("test")
@EnableJpaAuditing
class MyClassTests {

    @Autowired
    private CustomerRepository customerRepository;

    @Test
    void given_a_customer_should_have_customerId_and_id_equal(){
        Customer customer = new Customer();
        customerRepository.save(customer);
        // if i don't call findOneByCustomerId test fails for both @SpringBootTest and @DataJpaTest
        customer = customerRepository.findOneByCustomerId(customer.getCustomerId());
        assertEquals(customer.getCustomerId(), customer.getId()); // expected: 1, actual 0
    }
}
like image 580
Vasilis Konstantinou Avatar asked Oct 28 '25 02:10

Vasilis Konstantinou


1 Answers

If you use @DataJpaTest

By default, data JPA tests are transactional and roll back at the end of each test. See the relevant section in the Spring Framework Reference Documentation for more details

If you use @SpringBootTest that is not the case. But, if you add @Transational to your Class, the test will fail.

Solution:

@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyClassTests {
  ...

Propagation.NOT_SUPPORTED states that if a physical transaction exists, then it will be suspended before continuing. This physical transaction will be automatically resumed at the end. After this transaction is resumed, it can be rolled back (in case of a failure) or committed.

like image 59
Dirk Deyne Avatar answered Oct 30 '25 23:10

Dirk Deyne