Unit testing JUnit测试用例:java.lang.NullPointerException

Unit testing JUnit测试用例:java.lang.NullPointerException,unit-testing,spring-data-jpa,junit4,Unit Testing,Spring Data Jpa,Junit4,我正在尝试为存储库编写JUnit测试用例。我添加了H2内存中的数据库依赖项,还为H2数据库设置了配置。但是我得到了空指针异常。有人能告诉我我在代码上做错了什么吗 系 @Entity @Table(name = "department") @JsonInclude(JsonInclude.Include.NON_NULL) public class Department implements Serializable { private static final long serialV

我正在尝试为
存储库
编写
JUnit
测试用例。我添加了
H2
内存中的数据库依赖项,还为H2数据库设置了配置。但是我得到了
空指针异常
。有人能告诉我我在代码上做错了什么吗

@Entity
@Table(name = "department")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Department implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "department_seq_generator")
    @SequenceGenerator(name = "department_seq_generator", sequenceName = "department_seq")

    @Column(name = "ndept_id")
    public Integer nDeptId;

    @Column(name = "sdept_name")
    public String sDeptName;

    @Column(name = "ninst_id")
    public Integer nInstId;

    @Column(name = "bis_locked")
    public Boolean bIsLocked;

    @Column(name = "sclient_dept_id")
    public String sClientDeptId;

    @Column(name = "nsurvey_method_id")
    public Integer nSurveyMethodId;

    @Column(name = "bis_jointuse")
    public Boolean bIsJointuse;

    @Column(name = "ntemp_dept_id")
    public Integer nTempDeptId;

    @Column(name = "balternate_jointuse_percentage")
    public Boolean bAlternateJointusePercentage;

    @Column(name = "ndiv_id")
    public Integer nDivId;

    // Getter and Setter
depaertionrepository

@Repository
    public interface DepaertmentRepository extends JpaRepository<Department, Integer> {

        Department findByNDeptId(Integer nDeptId);
    }
持久异常的堆栈跟踪

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.spacestudy.model.Department
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1608)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1152)
    at org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager.persist(TestEntityManager.java:93)
    at com.spacestudy.DepartmentRepositoryTest.TestFindById(DepartmentRepositoryTest.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.spacestudy.model.Department
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:775)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:748)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:753)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1146)
    ... 31 more
使用上述代码测试用例成功运行,没有出现空指针异常。但当我在每一行设置检查点时,我观察到我正在将
nDeptId
保存为
1
,在这里合并数据库
saveInDB.getnDeptId()
后,我得到了
50
。我不明白为什么50岁不是1岁

这可能会有帮助

问题在这里:
Department found=depRepo.findByNDeptId(1)
您希望返回数据,而不是null

默认情况下,用
@DataJpaTest
注释的测试将使用嵌入式内存数据库(替换任何显式或通常自动配置的数据源)

因此,根据您在问题中提供的信息:

  • 检查是否有预期的测试数据。您需要在内存数据库或使用的数据库中保存ID为1的记录
  • 如果没有,则需要先准备一些测试数据(例如,在测试类中添加@BeforeClass方法,在运行测试之前可以插入一些测试数据)
  • 也许当您使用entityManager创建测试数据时(这一行
    entityManager.merge(dep);
    ),它会将数据保存到另一个数据库中?不是你正在读的那个?无论如何,最好在运行测试之前创建测试
例如

更新:

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "department_seq_generator")
    @SequenceGenerator(name = "department_seq_generator", sequenceName = "department_seq")

    @Column(name = "ndept_id")
    public Integer nDeptId;
根据这段代码,数据库中有一个序列,负责为新记录创建ID

基本工作原理:当您保存新记录时,会调用类似于
sequence get me next id
的函数,您将获得该id

这就是为什么即使你设置了一些ID(你不应该做的事情),你也会得到一个完全不同的数字

所以,这就是您可以修改测试的方式:

@Test
public void TestFindById() {

    Department dep = new Department();
    // you can set some fields here but not ID

    // this is saved entity, it means it has an ID assigned by the database
    Department saveInDB = em.merge(dep);        

    // that is what you need
    final Integer newRecordID = getFromDB.getnDeptId();

    // test your repository or what you need
    Department getFromDB = depRepo.findByNDeptId(newRecordID);


    // all asserts that you need
    assertThat(getFromDB).isEqualTo(saveInDB);
} 

答案在这里:
System.out.println(find);//这里我得到的是null,因此此行
depRepo.findByNDeptId(1)
不返回任何内容。要么模拟这个调用,要么修复它(我不知道为什么它应该返回一些东西,您是否有一些测试数据源用于测试,或者它是如何工作的??)我正在使用H2数据库。我不明白为什么要添加部门代码!!!我知道为什么我得到空指针异常。我将setnDeptId设置为1,但以DB为单位可以节省50。但为什么不节省50元呢1@SpringUser我想这需要一些调试。您是否可以尝试使用
em.persist(dep)
而不是
em.merge(dep)
保存测试记录?顺便问一下,如果我使用的是
em.persist(dep)
我得到的是
persistenceException
。在一些帖子中,我阅读了解决方案,我们可以使用
merge
而不是
persist
如果我使用
depRepo.save(dep)
,那么我也会得到50分
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "department_seq_generator")
    @SequenceGenerator(name = "department_seq_generator", sequenceName = "department_seq")

    @Column(name = "ndept_id")
    public Integer nDeptId;
@Test
public void TestFindById() {

    Department dep = new Department();
    // you can set some fields here but not ID

    // this is saved entity, it means it has an ID assigned by the database
    Department saveInDB = em.merge(dep);        

    // that is what you need
    final Integer newRecordID = getFromDB.getnDeptId();

    // test your repository or what you need
    Department getFromDB = depRepo.findByNDeptId(newRecordID);


    // all asserts that you need
    assertThat(getFromDB).isEqualTo(saveInDB);
}