2016-03-25 25 views
7

Ho classi @Entity in un pacchetto esterno che dispongono anche di metamodelli statici. Nella classe di servizio della mia applicazione, sto utilizzando quei metamodelli e EntityManager/CriteriaBuilder/CriteriaQuery per recuperare i miei dati. Funziona bene quando si esegue l'applicazione. Tuttavia, durante l'esecuzione dei test delle unità, i miei metamodelli e i loro attributi sono sempre nulli.Attributi di Metamodel statici nulli durante il test dell'unità

Codice ...

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; 
} 

uso in classe di servizio del mio app ...

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(); 
    //... 
    } 
} 

La classe "RepositoryQueryBuilder" è solo una classe di costruttore di utility che avvolge un EntityManager, CriteriaBuilder, ecc Fondamentalmente modellato dopo questo esempio ... JPA Criteria Predicate Conditions

Codice di prova unità ...

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

Ho guardato questo JPA/Hibernate Static Metamodel Attributes not Populated -- NullPointerException, ma la soluzione sembra essere "fare in modo che l'entità e la sua metamodello sono nello stesso pacchetto", ma come si può vedere, entrambi sono già nel mio pacchetto "com.example.core.entities".

Sto utilizzando tutto il bean e la configuazione guidata da annotazione nel mio codice (nessun file xml di persistenza o contesto). Per quanto riguarda i test, sto utilizzando TestNG e PowerMock da IntelliJ.

Sembra proprio che i metamodelli non vengano prelevati durante i test unitari. Qualche idea.

+0

Sembra che il processore JPA debba fornire istanze per le proprietà SingularAttribute. Hai trovato qualche soluzione per il test dell'unità? – srnjak

+0

Ho un problema simile. Sto usando Statics ma senza criteri, come: 'selezionare o.id, o." + Entity_.attribute.getName() + "FROM Entity o ...' Ho 2 test, ma il primo funziona bene, ma il secondo non riconosce il meta modello statico e lancia NPE – FiruzzZ

risposta

1

Le classi di metamodel statiche vengono popolate quando viene caricato lo stato di ibernazione. Quindi, si configura il contesto di ibernazione nel test o si compila manualmente gli attributi prima dell'esecuzione del metodo. In te codice, si potrebbe fare:

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

La classe SingularAttributeMock possono essere creati in modo da utilizzare nei vostri test su misura. È inoltre possibile utilizzare qualsiasi altra implementazione della classe SingularAttribute.

0

Non è necessario l'inizializzazione manuale. È necessario osservare le seguenti regole:

  • Le classi Metamodel devono essere dichiarate come classe astratta.
  • Le classi Metamodel devono essere nello stesso pacchetto delle classi di entità che descrivono ;
  • Dovrebbero avere lo stesso nome delle classi di entità che descrivono seguito da un trattino di sottolineatura (ad esempio Prodotto è l'entità, Product_ è la classe metamodel);
  • Se un'entità eredita da un'altra entità o da una superclasse mappata, la sua classe metamodello deve ereditare dalla classe metamodel che descrive la sua superclasse immediata (ad es.se SpecialProduct estende il Prodotto, che estende PersistentObject, allora SpecialProduct_ dovrebbe estendere Prodotto_ che dovrebbe estendere PersistentObject_).