Why is EntityGraph not working with DataJpaTest?

207 Views Asked by At

Hey today i found out that my Repository-Test runs perfectly fine when i use the @SpringBootTest-Annotation. But when i switch it to @DataJpaTest-Annotation, my @OneToMany-Annotated Collection of child elements is null.

Here an example:

ParentEntity.class

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@NamedEntityGraph(name="parent.childs", attributeNodes = @NamedAttributeNode("childEntities"))
@Table(name = "parent")
public class ParentEntity {


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    Integer id;

    @OneToMany(mappedBy = "parentId")
    Collection<ChildEntity> childEntities;

}

ParentRepository.class

@Repository
public interface ParentRepository extends JpaRepository<ParentEntity, Integer> {
    @EntityGraph(value = "parent.childs")
    Optional<ParentEntity> findById(Integer id);
}

ChildEntity.class

@Data
@Entity
@Table(name = "child")
public class ChildEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id", nullable = false)
    private Integer id;
    
    @Column(name = "parentId", nullable = false, insertable = false, updatable = false)
    private Integer parentId;

    @ManyToOne@JoinColumn(name = "parentId", referencedColumnName = "id", nullable = false)
    private ParentEntity parentEntity;

}

ChildRepository.class

@Repository
public interface ChildRepository extends JpaRepository<ChildEntity, Integer> {
}

And this is the Test:

@SpringBootTest
@AutoConfigureTestDatabase
public class RepoTest {
    @Autowired
    ParentRepository parentRepository;

    @Autowired
    ChildRepository childRepository;

    @Commit
    @Rollback(false)
    @Test
    void test(){
        /* arrange */
        ParentEntity parent = new ParentEntity();
        var parentId = parentRepository.save(parent).id;

        ChildEntity child = new ChildEntity();
        child.setParentEntity(parent);
        childRepository.save(child);

        /* act */
        /* Yes, i know there should be an exists()-check but lets keep it simple */
        ParentEntity returnedParent = parentRepository.findById(parentId).get();

        /* assert */
        assertThat(returnedParent.getChildEntities()).hasSize(1);
    }
}

This test works as expected.

But when i change the @SpringBootTest-Annotation to @DataJpaTest, the childEntities-Field of the ParentEntity.class stays null

I tried to delombok the code and find the cause by debugging each step of the query but i couldnt make it out right now. The resulting hibernate query contains the left outer join that i would expect. So my guess is that the error has to do with Data-Binding. Maby some type of (auto-)configuration is not loaded when i run the test with the other annotation.

I am very interested in the cause, so I would appreciate an explanation

1

There are 1 best solutions below

0
On

After a lot of further research, i found the following helpful link:

Spring Data Jpa Test returns null list even after child is saved

There is explained what the cause of the problem is:

The parent

gets not loaded for the database but from the internal cache.

And to solve this problem:

You need to write a FlushAndClear method

   @PersistenceContext
   private EntityManager em;

   private void flushAndClear() {
      em.flush();
      em.clear();
   }