I'm practicing TDD,
So now I'm trying to make a test that will fail for now. About to test a @Entity
that don't have a field relationship mapped so far. So I'm expecting my test to fail.
Here is TableA entity, you may notice that the TableB relationship is annotated with @Transient
, so this field does not get persisted and don't get errors when running other integration tests ( tests that uses @RunWith(SpringRunner.class)
.
@Builder
@Table(name = "table_a")
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class TableAData {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Setter
private String name;
@Transient
@Builder.Default
private List<TableBData> tableBs = List.of();
}
Here is the code for TableB entity, nothing really interesting about it.
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "table_b")
public class TableBData {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Setter
private String name;
}
I also have a TableAJpaRepository, this extends JpaRepository<TableAData, Long>
:
public interface TableAJpaRepository extends JpaRepository<TableAData, Long> {
public Optional<TableAData> findByName(String name);
}
My question is: Why does the follow test is not falling?
@DataJpaTest
@RunWith(SpringRunner.class)
public class TableAJpaRepositoryIntegrationTest {
@Autowired
private TableAJpaRepository repository;
@Test
public void dataFechedByIdWhenGetTableBsShouldBringTableB() {
TableBData tableBItem = TableBData.builder()
.name("123 Test")
.build();
TableAData tableAItem = TableAData.builder()
.name("TableAEntryName")
.tableBs(List.of(tableBItem))
.build();
Long id = repository.save(archetype).getId();
repository.flush();
TableAData fetched = repository.getOne(id);
assertThat(fetched.getTableBs()).isNotEmpty(); // This should be falling
assertThat(fetched.getTableBs().get(0).getName()).isEqualTo("123 Test");
}
}
Looks like getTableBs method is returning the other table entity from relationship, but I don't have it mapped. Am I missing something?
CodePudding user response:
So my friend and I spent some time trying to figure out what was going on. We've found this github issue that describes exactly the same issue. The person who open the issue also create a repo with a minimum reproducible example. One other thing that helped a lot was this SO answer: You fell in the trap of JPAs first level cache.
Looks like it's because of a cache.
To summarize, the solution was:
- Inject
TestEntityManager
to persist and setup test scenario. - Always using
TestEntityManager.persistAndFlush()
method. - Call
TestEntityManager.clear()
before starting tests. - Repositories was used normally in test cases.