2016-03-25 17 views
7

Tôi có các lớp @Entity trong gói bên ngoài cũng có các metamodels tĩnh. Trong lớp dịch vụ của ứng dụng của tôi, tôi đang sử dụng các metamodels đó và EntityManager/CriteriaBuilder/CriteriaQuery để lấy dữ liệu của mình. Điều này hoạt động tốt khi chạy ứng dụng. Tuy nhiên, khi chạy thử nghiệm đơn vị, metamodels của tôi và các thuộc tính của chúng luôn là null.Thuộc tính Metamodel tĩnh khi kiểm tra đơn vị

Mã ...

package com.example.core.entities; 

@Entity 
@Table(schema = "lookup", name="BookingSystem") 
public class BookingSystem implements ILookupEntity, IAuditEntity, Serializable { 
    @Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "id") 
    public Integer id; 

    @Column(name = "name") 
    public String name; 

    @Column(name = "code") 
    public Integer code; 
} 

package com.example.core.entities; 

@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor") 
@StaticMetamodel(BookingSystem.class) 
public abstract class BookingSystem_ { 
    public static volatile SingularAttribute<BookingSystem, Integer> id; 
    public static volatile SingularAttribute<BookingSystem, Integer> code; 
    public static volatile SingularAttribute<BookingSystem, String> name; 
} 

Cách sử dụng trong lớp dịch vụ ứng dụng của tôi ...

package com.example.bookingsystem; 

@Service 
public class BookingService { 
    @PersistenceContext 
    private EntityManager entityManager; 

public void saveBooking(Booking booking) { 
//... 
    RepositoryQueryBuilder<BookingSystem> bookingSystemSelector = new RepositoryQueryBuilder<>(entityManager, BookingSystem.class); 
    List<BookingSystem> bookingSystems = bookingSystemSelector 
     .and(BookingSystem_.code, booking.bookingSystem.code) //<-- Here "BookingSystem_.code" is null. 
     .getResultList(); 
    //... 
    } 
} 

Các "RepositoryQueryBuilder" class chỉ là một lớp người xây dựng tiện ích mà kết thúc tốt đẹp một EntityManager, CriteriaBuilder, vv Theo mô hình cơ bản sau ví dụ này ... JPA Criteria Predicate Conditions

Mã kiểm tra đơn vị ...

package com.example.bookingsystem; 

public abstract class BaseTestSetup { 
    @InjectMocks 
    protected BookingService bookingService; 

    protected EntityManager entityManager = PowerMockito.mock(EntityManager.class); 
    protected CriteriaBuilder criteriaBuilder = PowerMockito.mock(CriteriaBuilder.class); 
    protected CriteriaQuery<BookingSystem> criteriaQuery = PowerMockito.mock(CriteriaQuery.class); 
    protected Root<BookingSystem> root = PowerMockito.mock(Root.class); 

    protected void arrange() { 
    when(entityManager.getCriteriaBuilder()).thenReturn(criteriaBuilder); 
    when(criteriaBuilder.createQuery(BookingSystem.class)).thenReturn(criteriaQuery); 
    when(criteriaQuery.from(Matchers.<Class<BookingSystem>>any())).thenReturn(root); 
    when(criteriaQuery.from(Matchers.<EntityType<BookingSystem>>any())).thenReturn(root); 
} 

}

@RunWith(PowerMockRunner.class) 
public class BookingServiceTest extends BaseTestSetup { 
    @BeforeClass 
    @Override 
    public void arrange() { 
    super.arrange(); 

    //... 
} 

@Test 
public void doIt() { 
    Booking booking = new Booking(); 
    booking.id = 12345; 
    booking.bookingSystem = new BookingSystem(); 
    booking.bookingSystem.id = 1; 
    booking.bookingSystem.code = 106000; 

    bookingService.saveBooking(booking); 
    } 
} 

Tôi đã nhìn JPA/Hibernate Static Metamodel Attributes not Populated -- NullPointerException này, nhưng giải pháp có vẻ là "chắc chắn rằng thực thể và metamodel của nó là trong cùng một gói", nhưng như bạn có thể thấy, cả hai đều đã có trong gói "com.example.core.entities" của tôi.

Tôi đang sử dụng tất cả các cấu hình được định hướng bằng bean và chú thích trong mã của tôi (không có tệp xml kiên trì hoặc bối cảnh). Theo như thử nghiệm đi, tôi đang sử dụng TestNG và PowerMock từ bên trong IntelliJ.

Có vẻ như các metamodels không được chọn trong các bài kiểm tra đơn vị. Bất kỳ ý tưởng nào.

+0

Dường như bộ xử lý JPA nên cung cấp các phiên bản cho thuộc tính SingularAttribute. Bạn có tìm thấy giải pháp nào cho thử nghiệm đơn vị không? – srnjak

+0

Tôi gặp sự cố tương tự. Tôi đang sử dụng Statics nhưng không có tiêu chí, chẳng hạn như: 'select o.id, o." + Entity_.attribute.getName() + "FROM Entity o ...' Tôi có 2 kiểm tra, nhưng đầu tiên hoạt động tốt, nhưng người thứ 2 không nhận ra mô hình meta tĩnh và ném NPE – FiruzzZ

Trả lời

1

Các lớp metamodel tĩnh được điền khi tải ngủ đông. Vì vậy, hoặc bạn cấu hình bối cảnh ngủ đông trong thử nghiệm của bạn hoặc bạn cư các thuộc tính bằng tay trước khi thực hiện phương pháp. Trong bạn mã, bạn có thể làm:

@Test 
public void doIt() { 
    BookingSystem_.code = new SingularAttributeMock<BookingSystem, Integer>(); 
    bookingService.saveBooking(booking); 
    } 
} 

Lớp SingularAttributeMock có thể được tạo custom-made để sử dụng nó trong các thử nghiệm của bạn. Bạn cũng có thể sử dụng bất kỳ triển khai nào khác của lớp học SingularAttribute.

public class SingularAttributeMock<X, Y> implements SingularAttribute<X, Y> { 
    //Overriding methods of SingularAttribute... 
} 
0

Không cần khởi tạo thủ công. Bạn nên tuân thủ các quy tắc sau:

  • Lớp siêu mô hình phải được khai báo là lớp trừu tượng.
  • Các lớp Metamodel phải nằm trong cùng một gói với các lớp thực thể mà chúng mô tả ;
  • Họ phải có cùng tên với các lớp thực thể mà họ mô tả, theo sau là dấu gạch dưới (ví dụ: Sản phẩm là thực thể, Sản phẩm_ là lớp siêu mô hình);
  • Nếu một thực thể thừa kế từ một thực thể hoặc từ một lớp cha được ánh xạ khác, lớp siêu mô hình của nó phải là kế thừa từ lớp siêu mô hình mô tả lớp con ngay lập tức của nó là (ví dụ:nếu SpecialProduct mở rộng Sản phẩm, mở rộng PersistentObject, thì SpecialProduct_ sẽ mở rộng Product_ mà sẽ mở rộng PersistentObject_).
Các vấn đề liên quan