我正在尝试使用@DataJpaTest
注释设置数据库单元测试,以避免加载完整的Spring应用程序上下文。但是它的执行方式与使用@SpringBootTest
+配置的H2数据库时不同。当我使用H2数据库时,尝试保存具有空ID的实体时会收到适当的异常。
JdbcSQLIntegrityConstraintViolationException:“ ID_PART_2”列不允许使用NULL
但是当我使用here所述的@DataJpaTest
自动配置的数据库时
默认情况下,它配置内存中的嵌入式数据库,扫描@Entity类,并配置Spring Data JPA存储库
存储库允许插入具有空ID的实体。
我实体的代码是:
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)
自动配置的数据库,但是它没有任何改变。
注意:仅嵌入式ID会出现问题。对于我在stacktraces中看到的内容,在javax.persistence.Id
的情况下,Spring JPA甚至在尝试将此类实体保存到数据库之前都无法通过验证。
为什么使用@DataJpaTest
和@SpringBootTest
时行为会有所不同?使用@DataJpaTest
时使用什么数据库?我认为,如果Spring在这两种情况下都使用H2,就可以解决问题,但我不知道该如何实现。