0

I am trying to write JUnit test case for Repository. I added H2 in memory database dependency also setup configuration for h2 database. But I am getting null pointer exception. Can any one please tell me what I am doing wrong in code?

Department

@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

DepaertmentRepository

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

        Department findByNDeptId(Integer nDeptId);
    }

DepartmentRepositoryTest

@RunWith(SpringRunner.class)
@DataJpaTest
public class DepartmentRepositoryTest { 

    @Autowired
    private static DepaertmentRepository depRepo; 

    @Autowired
    public TestEntityManager em;        

@Test
public void TestFindById() {

    Department dep = new Department();
    dep.setnDeptId(1);

    System.out.println(dep.getnDeptId());// here i am getting 1

    Department saveInDB = em.merge(dep);        

    System.out.println(saveInDB.getnDeptId());// here i am getting 50

    Department getFromDB = depRepo.findByNDeptId(saveInDB.getnDeptId());

    System.out.println(getFromDB.getnDeptId());// here i am getting 50

    assertThat(getFromDB).isEqualTo(saveInDB);
}       
}

Stack Trace for PersistenceException

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

Using above code Test case is running successfully without null pointer exception. But when I putted checkpoint at every line I observer that I am saving nDeptId as 1 after merge in DB here saveInDB.getnDeptId() I am getting 50. I didn't understood why its coming 50 not 1;

3
  • The answer is here : System.out.println(found);// here i am getting null So this line depRepo.findByNDeptId(1) returns nothing. Either mock this call or fix it (I don't know why it should return something, do you have some test DataSource that you are using for tests or how it works??) Commented May 2, 2018 at 14:13
  • I am using H2 database. I am not getting why depRepo.findByNDeptId(1) coming null Commented May 2, 2018 at 14:18
  • Add your Department code as well !!! Commented May 3, 2018 at 13:25

1 Answer 1

1

This might be helpful!

The problem is here : Department found = depRepo.findByNDeptId(1); You expect data to be returned instead of null.

By default, tests annotated with @DataJpaTest will use an embedded in-memory database (replacing any explicit or usually auto-configured DataSource).

So based on what you provided in your question:

  • Check if you have test data you expect. You need to have that record with ID = 1 in your in-memory database or the DB you use.
  • If you don't have you need to prepare some test data first (e.g. in your test class add @BeforeClass method where you can insert some test data before running your test)
  • Maybe when you create your test data using entityManager (this line entityManager.merge(dep);) it saves it to another DB? Not the one you are reading after? Anyway, it's better to create test before you run your test.

E.g.

@BeforeClass
public static void init() {
    // you could try instead of this to use your Repository to create test data
    Department dep = new Department();
    dep.setnDeptId(1);
    // entityManager.merge(dep);
    yourRepo.save(dep);    
}

Update:

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

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

According to this code, there is a sequence on your database, that is responsible for creating IDs for new records.

Basically how it works: when you save the new record, something like sequence get me next id is called and you are getting the ID.

That's why even if you set something to the ID (what you should not do), you are getting a completely different number!

So, that's how you could modify your test:

@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);
} 
Sign up to request clarification or add additional context in comments.

9 Comments

I got why I am getting null pointer exception. I am setting setnDeptId as 1 but in DB its saving 50. but why its saving 50 not 1
@SpringUser it requires some debugging I guess. Can you try to save your test record with em.persist(dep) instead of em.merge(dep)? And check if it makes any difference.
@SpringUser why you are using merge there by the way ?
If i am using em.persist(dep) I am getting persistenceException. In some post i read solution for that we can use merge instead of persist
if I am using depRepo.save(dep) then also i am getting 50
|

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.