用@Transient 注释的字段被保存在@DataJpaTest 中

Field annotated with @Transient being persisted in @DataJpaTest

我正在练习 TDD, 所以现在我正在尝试进行暂时失败的测试。即将测试目前尚未映射字段关系的 @Entity。所以我预计我的测试会失败。

这里是 TableA 实体,你可能会注意到 TableB 关系用 @Transient 注释,所以这个字段不会被持久化并且在 运行 其他集成测试时不会出错(测试使用 @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();
}

这是 TableB 实体的代码,没有什么有趣的地方。

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "table_b")
public class TableBData {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Setter
    private String name;

}

我还有一个 TableAJpaRepository,它扩展了 JpaRepository<TableAData, Long>:

public interface TableAJpaRepository extends JpaRepository<TableAData, Long> {

    public Optional<TableAData> findByName(String name);

}

我的问题是: 为什么follow测试不下降?

@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");
    }

}

看起来 getTableBs 方法正在从关系中返回另一个 table 实体,但我没有映射它。我错过了什么吗?

所以我和我的朋友花了一些时间试图弄清楚发生了什么。我们找到了 this github issue that describes exactly the same issue. The person who open the issue also create a repo with a minimum reproducible example。 另一件很有帮助的事情是这个 SO 答案:.

看起来是因为缓存。

总而言之,解决方案是:

  • 注入 TestEntityManager 以持久化并设置测试场景。
  • 一直使用TestEntityManager.persistAndFlush()方法。
  • 在开始测试之前调用 TestEntityManager.clear()
  • 在测试用例中正常使用存储库。