簡體   English   中英

如何測試 Spring JPA 審計注釋?

[英]How to test Spring JPA audit annotations?

我無法使用 H2 內存數據庫測試 Spring JPA (2.5.4) 中的審計注釋。 我有一個用 @EnableJpaAuditing 注釋的主要@EnableJpaAuditing ,以及我的實體的基本 class 。

@Getter
@Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class AuditedEntity {
    @CreatedDate
    LocalDateTime createdDate;

    @LastModifiedDate
    LocalDateTime lastModifiedDate;
}

兩個實體擴展了基礎 class:父級和子級。

@Data
@Entity
@Table(name = "one2many")
class OneToManyEntity extends AuditedEntity {
    @Id
    @GeneratedValue(strategy = SEQUENCE)
    Integer id;

    @OneToMany(mappedBy = "parent", cascade = ALL, orphanRemoval = true)
    List<ManyToOneEntity> children;
}

@Data
@Entity
@Table(name = "many2one")
class ManyToOneEntity extends AuditedEntity {
    @Id
    @GeneratedValue(strategy = SEQUENCE)
    Integer id;

    @ManyToOne(optional = false, fetch = LAZY)
    OneToManyEntity parent;
}

父實體的存儲庫是一個簡單的接口聲明。

@Repository
interface OneToManyRepository extends CrudRepository<OneToManyEntity, Integer> {
}

我有幾個Spock測試。

class OneToManyRepoSpec extends Specification {
    @Autowired
    OneToManyRepository repo

    def "test ID is assigned"() {
        given:
            def parent = new OneToManyEntity()
            parent.setChildren([new ManyToOneEntity()])
        expect:
            def persisted = repo.save(parent)
            persisted.getId() > 0
            persisted.getLastModifiedDate() != null
    }

    def "LastModifiedDate value is updated"() {
        given:
            def persisted1 = repo.save(new OneToManyEntity())
            sleep(1000)
            persisted1.setChildren([])
            def persisted2 = repo.save(persisted1)
        expect:
            persisted2.lastModifiedDate.isAfter(persisted1.lastModifiedDate)
    }
}

我可以通過這些測試中的任何一個,這取決於我如何注釋測試 class; 但我不能讓兩個測試一起通過。

  • 如果我用@DataJpaTest注釋測試 class ,則第一個測試通過(分配了 ID 和審計值),但第二個測試失敗(未更新審計值)。
  • 如果我用@SpringBootTest(webEnvironment = NONE)注釋測試 class ,則第一個測試失敗( ConstraintViolationException: NULL not allowed for column "parent_id";因此未分配 ID)但第二個測試通過(更新審核值)。

我是否必須將這些測試分成具有不同注釋的不同類,或者有沒有辦法將它們保持在一起並且都通過? 我也有興趣更多地了解導致這些單獨測試失敗的原因。

就像我說的,我不是 Spring 用戶,但在玩你的 MCVE 時我注意到以下幾點:

  • 對於@DataJpaTest ,不僅persisted2 == persisted1是真的,甚至是persisted2 === persisted1 即,object 就地更改,沒有創建新實例。 因此,檢查persisted2.lastModifiedDate.isAfter(persisted1.lastModifiedDate)永遠無法工作。
  • 對於@DataJpaTestlastModifiedDate永遠不會更新。 也許這種測試並不意味着檢查時間戳。 即你甚至不能在保存第二次之前使用def lastModifiedDate = persisted1.lastModifiedDate ,后來又保存了persisted2.lastModifiedDate.isAfter(lastModifiedDate) 它也失敗了。

所以你真的應該使用@SpringBootTest ,如果你想檢查這樣的時間戳。 但是,您需要滿足父子關系的參照完整性。 如果有一個選項可以修改@DataJpaTest行為以更新時間戳,我不知道。 但這可能是在 JPA 測試中被嘲笑的數據庫功能。 在 Spring 方面更有經驗的人也許可以回答這個問題。

感謝評論中的提示,我意識到這兩個測試在相反的情況下失敗,因為第一個測試必須在事務中運行,而第二個測試不能在事務中運行。 測試失敗表現為不同的類級別注釋,因為@DataJpaTest是事務性的,而@SpringBootTest不是。 所以解決方案是使用@SpringBootTest並僅將第一個測試注釋為@Transactional 我已經相應地更新了 GitHub 項目

對於在 junit 測試中存儲在 DB 后未生成場景 fe @CreatedDate 的任何人。 只需將@DataJpaTest 與@EnableJpaAuditing 一起使用,您的@CreatedDate 和其他生成的字段也將在junit 測試中開始工作。 在我的案例中缺少的是 @EnableJpaAuditing 注釋。 @DataJpaTest 默認未啟用 jpa 審計,因此使用注釋 @EnableJpaAuditing 您將啟用它。 祝你好運:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM