簡體   English   中英

Spring 啟動測試 schema.sql/data.sql 違反約束錯誤

[英]Spring Boot Test schema.sql/data.sql contraint violation error

我的 src/test/resources 中的 schema-h2.sql 中有以下 sql

CREATE TABLE IF NOT EXISTS project.general_types(
  id SMALLINT PRIMARY KEY NOT NULL,
  name VARCHAR(15) NOT NULL);

我的 data.sql 具有以下內容

INSERT INTO project.general_types(id, name) VALUES 
   (0, 'Text'),
   (1, 'Binary');

應用測試.yml

spring:
  datasource:
    url: jdbc:h2:mem:testdb;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;DATABASE_TO_UPPER=false;
    username: sa
    password: 
    driver-class-name: org.h2.Driver
    initialization-mode: always
    platform: h2    
  jpa:
    generate-ddl: false
    defer-datasource-initialization: true
    show-sql: true
    open-in-view: false
    hibernate:
      ddl-auto: none
    properties:
      hibernate:
        format_sql: true
        default_schema: project
        dialect: org.hibernate.dialect.H2Dialect  
        globally_quoted_identifiers: true

映射它的實體。

@Entity(name = "general_types")
public class GeneralTypesEntity {

  @Id
  private short id;
  @Basic
  private String name;

//getters/setters nor shown...
}

測試用例

@SpringBootTest
@ActiveProfiles("test")
class GeneralTypesDbTest {

  @Autowired
  private final GeneralTypesRepository generalTypesRepository = null;

  @Test
  void test() {

    assertNotNull(generalTypesRepository);
    assertEquals(2, generalTypesRepository.count());
  }

}

在生產中使用 PostgreSQL 可以正常工作(預構建的數據庫和所有回購協議、實體等...)。 我現在正在嘗試使用 h2 設置 Spring 啟動測試。 如果我僅使用 schema.sql 運行,它可以正常構建並運行測試。

將data.sql與insert語句相加,創建默認數據集,執行Spring錯誤

Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PRIMARY KEY ON project.general_types(id) [0, 'Text']"; SQL statement:
INSERT INTO project.general_types(id, name) VALUES (0, 'Text'), (1, 'Binary') [23505-200]
   at org.h2.message.DbException.getJdbcSQLException(DbException.java:459) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.message.DbException.getJdbcSQLException(DbException.java:429) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.message.DbException.get(DbException.java:205) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.message.DbException.get(DbException.java:181) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.mvstore.db.MVPrimaryIndex.add(MVPrimaryIndex.java:127) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.mvstore.db.MVTable.addRow(MVTable.java:531) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.command.dml.Insert.insertRows(Insert.java:195) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.command.dml.Insert.update(Insert.java:151) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.command.CommandContainer.update(CommandContainer.java:198) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.command.Command.executeUpdate(Command.java:251) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:228) ~[h2-1.4.200.jar:1.4.200]
   at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:201) ~[h2-1.4.200.jar:1.4.200]
   at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:94) ~[HikariCP-4.0.3.jar:na]
   at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) ~[HikariCP-4.0.3.jar:na]
   at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:261) ~[spring-jdbc-5.3.18.jar:5.3.18]
   ... 96 common frames omitted

我嘗試在創建表后立即將 Insert 放入 schema-h2.sql 並得到相同的錯誤。 關於如何導致約束違規的任何想法。 對於沒有自動遞增的新創建的表,我不清楚為什么插入會導致違反約束。

我的朋友,

如果你能拋出 Entity class 就好了。 但是我之前也遇到過類似的錯誤,我在 Entity class 中解決了我的問題。 如果您使用@GeneratedValue,您應該選擇正確的策略。 參考:baeldung.com/hibernate-identifiers

這是為我解決問題的代碼。 @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "ID") private Long id;

另外一個建議是在 data.sql 文件中進行所有 sql 查詢

顯示您的測試 class 會有所幫助,因為您的數據腳本似乎正在執行兩次

截至今天早上,它現在正在工作,我不知道為什么。 我會列出所做的事情,也許有人可以澄清為什么它會在 12 小時后開始工作。

由於 data.sql 導致重復密鑰問題,我將其重命名為 data-disabled.yml。 然后我將測試更改為使用 @Sql( statement="" ) 插入項目,並且測試使用 GeneralTypesRepository 來 findByName(string) (我試圖測試的方法)。 這通過構建 H2 DB (schema.sql) 成功運行,使用 @Sql 插入 1 項(0,“Text”),然后檢查該方法是否可以找到“Text”的記錄。 這過去了。 偉大的。

使用此方法(每個測試方法上的@Sql)為其他存儲庫(總共大約 8 個)構建了更多測試。

今天早上,當我看到更多信息的請求時,我創建了一個新的測試文件來復制重做我原來的測試。 我將 data-disabled.sql 重命名為 data.sql。 運行測試,它通過了。 沒有例外,junit 綠色。

我回到昨晚創建的另一個測試,刪除了所有@Sql 行,運行測試,它們都通過了。

沒有進行其他更改(通過 git 確認)。 我不知道為什么它開始工作。 這個測試現在正如我預期的那樣工作,因為 data.sql 是唯一完成插入的地方。

感謝推動更多信息的少數人。 對不起,我一開始就沒有。 抱歉,這並沒有對原始問題給出明確的答案,但我再次非常確定有一個 data.sql 文件只會運行一次,並使用創建數據庫的架構進行插入,而無需插入。

今天我有一個類似的失敗案例,並且能夠找出導致它的原因。 把它放在這里是為了將來幫助其他人。

基本上我進行測試,然后在添加 @PostContruct 之后我的一個數據庫測試開始失敗。 PostContruct 方法進行了數據庫調用以獲取最新記錄作為緩存。

這里的問題是 @PostContruct 將在 Spring App Context 啟動期間被調用。 這導致在 Spring 測試有機會使用測試資源文件初始化數據庫之前發生數據庫調用。 更改為在首次使用時構建緩存,現在問題消失了。 另一種選擇可能是更改為 @EventListener(ApplicationReadyEvent.class) 以使其在完全加載后在應用程序上下文之后啟動。

暫無
暫無

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

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