代码之家  ›  专栏  ›  技术社区  ›  Nicklas2751

Quarkus测试在本机中失败,因为找不到DayOfWeek

  •  0
  • Nicklas2751  · 技术社区  · 5 年前

    我创建了一个简单的quarkus(0.21.2版)应用程序,它使用hibernate orm和panache将实体保存到h2数据库。该实体包括 ElementCollection 属于 DaysOfWeek . 我还创建了一些测试来确保CURD工作正常。这些测试都很好,但当我在本地运行它们时,会出现以下异常:

    Exception in thread "main" java.lang.RuntimeException: Failed to start quarkus
        at io.quarkus.runner.ApplicationImpl1.doStart(ApplicationImpl1.zig:126)
        at io.quarkus.runtime.Application.start(Application.java:91)
        at io.quarkus.runtime.Application.run(Application.java:204)
        at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:34)
    Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
        at io.quarkus.hibernate.orm.runtime.boot.FastBootEntityManagerFactoryBuilder.persistenceException(FastBootEntityManagerFactoryBuilder.java:113)
        at io.quarkus.hibernate.orm.runtime.boot.FastBootEntityManagerFactoryBuilder.build(FastBootEntityManagerFactoryBuilder.java:67)
        at io.quarkus.hibernate.orm.runtime.FastBootHibernatePersistenceProvider.createEntityManagerFactory(FastBootHibernatePersistenceProvider.java:54)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
        at io.quarkus.hibernate.orm.runtime.JPAConfig$LazyPersistenceUnit.get(JPAConfig.java:109)
        at io.quarkus.hibernate.orm.runtime.JPAConfig.startAll(JPAConfig.java:57)
        at io.quarkus.hibernate.orm.runtime.HibernateOrmRecorder.startAllPersistenceUnits(HibernateOrmRecorder.java:77)
        at io.quarkus.deployment.steps.HibernateOrmProcessor$startPersistenceUnits19.deploy_0(HibernateOrmProcessor$startPersistenceUnits19.zig:51)
        at io.quarkus.deployment.steps.HibernateOrmProcessor$startPersistenceUnits19.deploy(HibernateOrmProcessor$startPersistenceUnits19.zig:70)
        at io.quarkus.runner.ApplicationImpl1.doStart(ApplicationImpl1.zig:90)
        ... 3 more
    Caused by: org.hibernate.MappingException: Could not create DynamicParameterizedType for type: org.hibernate.type.EnumType
        at org.hibernate.mapping.SimpleValue.createParameterImpl(SimpleValue.java:768)
        at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:470)
        at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:455)
        at org.hibernate.mapping.Collection.validate(Collection.java:315)
        at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:347)
        at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:461)
        at io.quarkus.hibernate.orm.runtime.boot.FastBootEntityManagerFactoryBuilder.build(FastBootEntityManagerFactoryBuilder.java:65)
        ... 12 more
    Caused by: org.hibernate.boot.registry.classloading.spi.ClassLoadingException: Unable to load class [java.time.DayOfWeek]
        at io.quarkus.hibernate.orm.runtime.service.FlatClassLoaderService.classForName(FlatClassLoaderService.java:39)
        at org.hibernate.mapping.SimpleValue.createParameterImpl(SimpleValue.java:755)
        ... 18 more
    Caused by: java.lang.ClassNotFoundException: java.time.DayOfWeek
        at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:60)
        at java.lang.Class.forName(DynamicHub.java:1174)
        at io.quarkus.hibernate.orm.runtime.service.FlatClassLoaderService.classForName(FlatClassLoaderService.java:37)
        ... 19 more
    

    我的实体看起来是这样的:

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
    import org.hibernate.annotations.Cascade;
    import org.hibernate.annotations.GenericGenerator;
    
    import javax.persistence.ElementCollection;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.validation.constraints.NotNull;
    import java.time.DayOfWeek;
    import java.time.LocalTime;
    import java.util.*;
    
    import static org.hibernate.annotations.CascadeType.ALL;
    
    @Entity
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class OpeningTimes extends PanacheEntityBase {
      @Id
      @GeneratedValue(generator = "UUID")
      @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
      private UUID id;
    
      @NotNull
      private String name;
      private String description;
      private LocalTime timeFrom;
      private LocalTime timeTo;
    
      @ElementCollection
      @Cascade(value = {ALL})
      private Collection<DayOfWeek> daysOfWeek;
    
      /**
       * DO NOT USE! ONLY FOR JPA!
       */
      OpeningTimes() {
        super();
        name = "";
      }
    
      @JsonCreator
      public OpeningTimes(
          @JsonProperty("name") String name,
          @JsonProperty("timeFrom") LocalTime timeFrom,
          @JsonProperty("timeTo") LocalTime timeTo,
          @JsonProperty("daysOfWeek") Collection<DayOfWeek> daysOfWeek) {
        this.name = name;
        this.timeFrom = timeFrom;
        this.timeTo = timeTo;
        this.daysOfWeek = new HashSet<>(daysOfWeek);
      }
    
      public OpeningTimes(String name, LocalTime from, LocalTime to, DayOfWeek... daysOfWeek) {
        this(name, from, to, new ArrayList<>(Arrays.asList(daysOfWeek)));
      }
    
      public LocalTime getTimeFrom() {
        return timeFrom;
      }
    
      public void setTimeFrom(LocalTime timeFrom) {
        this.timeFrom = timeFrom;
      }
    
      public LocalTime getTimeTo() {
        return timeTo;
      }
    
      public void setTimeTo(LocalTime timeTo) {
        this.timeTo = timeTo;
      }
    
      public Collection<DayOfWeek> getDaysOfWeek() {
        return daysOfWeek;
      }
    
      public void setDaysOfWeek(Set<DayOfWeek> daysOfWeek) {
        this.daysOfWeek = daysOfWeek;
      }
    
      public UUID getId() {
        return id;
      }
    
      public void setId(UUID id) {
        this.id = id;
      }
    
      public String getName() {
        return name;
      }
    
      public void setName(String name) {
        this.name = name;
      }
    
      public String getDescription() {
        return description;
      }
    
      public void setDescription(String description) {
        this.description = description;
      }
    
      @Override
      public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof OpeningTimes)) return false;
        OpeningTimes that = (OpeningTimes) o;
        return Objects.equals(getId(), that.getId())
                && Objects.equals(getName(), that.getName())
                && Objects.equals(getDescription(), that.getDescription())
                && Objects.equals(getTimeFrom(), that.getTimeFrom())
                && Objects.equals(getTimeTo(), that.getTimeTo())
                && Objects.equals(getDaysOfWeek(), that.getDaysOfWeek());
      }
    
      @Override
      public int hashCode() {
        return Objects.hash(
                getId(), getName(), getDescription(), getTimeFrom(), getTimeTo(), getDaysOfWeek());
      }
    
      @Override
      public String toString() {
        return "OpeningTimes{"
                + "id="
                + id
                + ", name='"
                + name
                + '\''
                + ", description='"
                + description
                + '\''
                + ", timeFrom="
                + timeFrom
                + ", timeTo="
                + timeTo
                + ", daysOfWeek="
                + daysOfWeek
                + '}';
      }
    
      public void merge(OpeningTimes openingTimes) {
        this.name = openingTimes.name;
        this.description = openingTimes.description;
        this.timeFrom = openingTimes.timeFrom;
        this.timeTo = openingTimes.timeTo;
        this.daysOfWeek = openingTimes.daysOfWeek;
      }
    }
    

    这是我的测试:

    import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
    import io.quarkus.test.common.QuarkusTestResource;
    import io.quarkus.test.h2.H2DatabaseTestResource;
    import io.quarkus.test.junit.QuarkusTest;
    import io.restassured.http.ContentType;
    import io.restassured.mapper.ObjectMapperType;
    import io.restassured.mapper.TypeRef;
    import io.restassured.response.Response;
    import org.junit.jupiter.api.AfterEach;
    import org.junit.jupiter.api.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.transaction.Transactional;
    import java.time.DayOfWeek;
    import java.time.LocalTime;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.List;
    
    import static io.restassured.RestAssured.given;
    import static org.hamcrest.CoreMatchers.equalTo;
    import static org.hamcrest.CoreMatchers.is;
    import static org.hamcrest.MatcherAssert.assertThat;
    
    @QuarkusTest
    @QuarkusTestResource(H2DatabaseTestResource.class)
    class OpeningsResourceTest {
      private static final Logger LOG = LoggerFactory.getLogger(OpeningsResourceTest.class);
    
      @Test
      void testSaveOpening() {
        OpeningTimes opening =
            new OpeningTimes(
                "Test opening", LocalTime.MIN, LocalTime.NOON, DayOfWeek.MONDAY, DayOfWeek.THURSDAY);
        Response response =
            given()
                .when()
                .contentType(ContentType.JSON)
                .body(opening, ObjectMapperType.JACKSON_2)
                .post("/service/events/openings");
        LOG.debug(response.andReturn().body().prettyPrint());
        OpeningTimes responseObject = response.then().statusCode(200).extract().as(OpeningTimes.class);
    
        // Set the id because its generated on saving
        opening.setId(responseObject.getId());
        assertThat(responseObject, equalTo(opening));
      }
    
      @Test
      void testGetOpening() {
        OpeningTimes testdata = saveTestdata().get(0);
        Response response = given().when().get("/service/events/openings/{id}/", testdata.getId());
        OpeningTimes responseObject = response.then().statusCode(200).extract().as(OpeningTimes.class);
        assertThat(responseObject, equalTo(testdata));
      }
    
      @Test
      void testDeleteOpening() {
        OpeningTimes testdata = saveTestdata().get(0);
        // Delete
        given()
                .when()
                .delete("/service/events/openings/{id}/", testdata.getId())
                .then()
                .statusCode(204);
        // Check if it is deleted
        given().when().get("/service/events/openings/{id}/", testdata.getId()).then().statusCode(204);
      }
    
      @Test
      void testChangeOpening() {
        OpeningTimes testdata = saveTestdata().get(0);
        testdata.setDescription("Example description");
        Response response =
                given()
                        .when()
                        .contentType(ContentType.JSON)
                        .body(testdata, ObjectMapperType.JACKSON_2)
                        .put("/service/events/openings/");
        LOG.debug(response.andReturn().body().prettyPrint());
        response.then().statusCode(200).extract().as(OpeningTimes.class);
    
        OpeningTimes changedOpening =
                given()
                        .when()
                        .get("/service/events/openings/{id}", testdata.getId())
                        .then()
                        .statusCode(200)
                        .extract()
                        .as(OpeningTimes.class);
        assertThat(changedOpening, is(testdata));
      }
    
      private List<OpeningTimes> saveTestdata() {
        OpeningTimes opening1 =
            new OpeningTimes(
                "Test opening", LocalTime.MIN, LocalTime.NOON, DayOfWeek.MONDAY, DayOfWeek.THURSDAY);
        OpeningTimes opening2 =
            new OpeningTimes("Test opening 2", LocalTime.MIN, LocalTime.NOON, DayOfWeek.FRIDAY);
        opening1 =
                given()
                        .contentType(ContentType.JSON)
                        .body(opening1, ObjectMapperType.JACKSON_2)
                        .post("/service/events/openings")
                        .then()
                        .extract()
                        .as(OpeningTimes.class);
        opening2 =
                given()
                        .contentType(ContentType.JSON)
                        .body(opening2, ObjectMapperType.JACKSON_2)
                        .post("/service/events/openings")
                        .then()
                        .extract()
                        .as(OpeningTimes.class);
        return Arrays.asList(opening1, opening2);
      }
    
      @Test
      void testGetAll() {
        List<OpeningTimes> testdata = saveTestdata();
        Collection<OpeningTimes> openings =
            given()
                .when()
                .get("/service/events/openings")
                .then()
                .statusCode(200)
                .extract()
                .as(new TypeRef<Collection<OpeningTimes>>() {});
    
        assertThat(openings, is(testdata));
      }
    
      @AfterEach
      @Transactional
      void cleanUpDatabase() {
        // Delete all won't work because of the element collection
        OpeningTimes.findAll().stream().forEach(PanacheEntityBase::delete);
      }
    }
    

    以及本地测试:

    import io.quarkus.test.junit.SubstrateTest;
    
    @SubstrateTest
    public class NativeOpeningsResourceIT extends OpeningsResourceTest {
        // Execute the same tests but in native mode.
    }
    

    我不知道为什么它找不到 java.time.DayOfWeek .

    0 回复  |  直到 5 年前
        1
  •  1
  •   loicmathieu    5 年前

    似乎本机映像工具没有包括 java.time.DayOfWeek 在本机映像中初始化。SubstratVM工作在一个封闭的世界中,只能访问在本机映像编译期间发现的类或那些为反射而专门注册的类。

    您可以按照此部分注册反射 java.time.DayOfWeek周 班级: https://quarkus.io/guides/writing-native-applications-tips#registering-for-reflection .

    您可以尝试在实体类上使用注释,但我认为您需要将 java.time.DayOfWeek周 类中的 reflection-config.json 文件,因为我不确定注释是否包含您的实体使用的所有类,或者仅包含您的实体类。