Я пытаюсь настроить свои модульные тесты БД, используя аннотацию @DataJpaTest
, чтобы избежать полной загрузки контекста приложения Spring. Но он не работает так же, как когда я использую настроенную базу данных @SpringBootTest
+ H2. Когда я использую базу данных H2, я получаю надлежащее исключение при попытке сохранить сущность с нулевым идентификатором.
JdbcSQLIntegrityConstraintViolationException: NULL не допускается для столбца "ID_PART_2"
Но когда я использую БД, автоматически настроенную с использованием @DataJpaTest
, как указано здесь
По умолчанию он настраивает встроенную базу данных в памяти, сканирует классы @Entity и настраивает репозитории Spring Data JPA
Хранилище позволяет вставлять сущности с нулевым идентификатором.
Код для моей сущности:
package com.mycompany.test.db;
import lombok.Data;
import javax.persistence.*;
import java.io.Serializable;
@Data
@Entity
@Table(name = "MY_TABLE", schema = "MY_SCHEMA")
public class MyEntity {
//Works fine when using @Id
// @Id
// @Column(name = "ID", nullable = false)
// private String id;
@EmbeddedId
private MyId myId;
@Data
@Embeddable
public static class MyId implements Serializable {
//Single field reproduces the problem
// @Column(name = "ID_PART_1", nullable = false)
// private String idPart1;
@Column(name = "ID_PART_2", nullable = false)
private String idPart2;
}
}
Я использую базовый репозиторий CRUD CrudRepository<MyEntity, MyEntity.MyId>
Код моего теста выглядит следующим образом:
package com.mycompany.test.db;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest//works as expected
//@DataJpaTest//doesn't work
public class MyRepositoryTest {
@Autowired
private MyRepository repository;
private MyEntity.MyId createMyId(String part1, String part2){
MyEntity.MyId myId = new MyEntity.MyId();
// myId.setIdPart1(part1);
myId.setIdPart2(part2);
return myId;
}
@Test
public void testSaveAndRead(){
MyEntity entity = new MyEntity();
entity.setMyId(createMyId("part1", "part2"));
repository.save(entity);
Assert.assertNotNull(repository.findById(createMyId("part1", "part2")));
}
@Test
public void testSaveWithNoPrimaryKeyFails(){
try{
MyEntity entity = new MyEntity();
entity.setMyId(createMyId("part1", null));
repository.save(entity);
Assert.fail();
}catch(Exception expected){
expected.printStackTrace();
}
}
}
Я также пытался отключить автоматически настраиваемую БД с использованием @DataJpaTest
, добавив @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
, но это ничего не изменило.
ПРИМЕЧАНИЕ : проблема возникает только для встроенных идентификаторов. Что я вижу в стековых трассах, в случае javax.persistence.Id
Spring JPA не проходит проверку, даже не пытаясь сохранить такую сущность в базе данных.
Почему поведение отличается при использовании @DataJpaTest
и @SpringBootTest
? Какая база данных используется при использовании @DataJpaTest
? Я думаю, что проблема была бы решена, если бы Spring использовал H2 в обоих случаях, но я не знаю, как этого добиться.