EE 6

Arquillian in testiranje storitev REST

Posted on

Arquillian je orodje za integracijsko testiranje komponent. V najbolj osnovni obliki je odgovor na vprašanje: kako naj stestiram nek EJB v njegovem okolju ? Članek ni namenjen osnovam Arquilliana, te lahko spoznate na:  http://jaxenter.com/arquillian-a-component-model-for-integration-testing.1-35304.html, ampak je namenjen prikazu testiranja:

storitve REST, ki je implementirana nad Stateless EJBjem, in glede na vhodni parameter poišče (preko JPA) določeno entiteto in jo vrne.

Za testiranje (za odjemalca) bomo uporabili knjižnico RESTEasy (http://www.jboss.org/resteasy/), za pretvorbo JSON v Java objekte in obratno, pa bomo uporabili knjižnico Jackson (http://jackson.codehaus.org).

Sam Arquillian pa bo konfiguriran v načinu Glassfish 3.1 Managed, več o tem na https://docs.jboss.org/author/display/ARQ/GlassFish+3.1+-+Managed.

Implementacija storitve REST

Da je REST sploh omogočen, moramo definirati t.i. Application Path:

@ApplicationPath("/resources")
public class RestApplication extends Application {}

nato lahko implementiramo storitev, sicer s pomočjo Stateless EJBja:

@Stateless
@Path("/alert")
public class TestResource {

    @Inject
    @PuAdminWH
    EntityManager entityManager;

    @GET
    @Path("/{id}")
    @Consumes("text/plain")
    @Produces("application/json")
    public AppJmsAlert getAlertById(@PathParam("id") int id) {

        //Tole lahko vrne NoResultException, glej Exception mapper        AppJmsAlert alert = ...koda za poizvedbo...

        return alert;
    }
}

Vidimo, da smo implementirali klic tipa GET, ki sprejme en parameter id tipa text in vrne JSON prezentacijo entitete JPA tipa AppJmsAlert, torej naš klic bo izgledal takole:

http://localhost:8080/.../resources/alert/id/1453

V primeru, da vhodni parameter ne vrne rezultata (ne vrne entitete JPA), se bo avtomatsko na strežniku sprožil NoResultException, odjemalcu pa v takem primeru želimo vrniti odgovor s statusom HTTP tipa BAD_REQUEST. Zato moramo implementrati t.i. Exception Mapper:

@Provider
public class NoResultExceptionMapper implements ExceptionMapper<NoResultException> {

    @Override
    public Response toResponse(NoResultException e) {

        return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
    }
}

Konfiguracija orodja Arquillian

Na lokacijo src/test/resources ustvarimo dve datoteki:

 arquillian.launch in arquillian.xml

ki nam predstavljata konfiguracijo. V launch datoteko bomo vpisali t.i. Container Qualifier, ki določa, katera konfiguracija, določena v arquillian.xml, je aktualna ob zagonu testov. Zato bo njena vsebina naslednja:

remote-gf

Arquillian.xml pa ima naslednjo vsebino:

<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.org/schema/arquillian"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">

    <container qualifier="remote-gf" default="true">
       <configuration>
          <property name="glassFishHome">
               /Applications/NetBeans/glassfish-3.1.2.2
          </property>
       </configuration>
    </container>
</arquillian>

vidimo, da je potrebno definirati pot do kontejnerja EE, v tem primeru Glassfish, katerega bo Arquillian zagnal, v njega namestil testni war in zagnal teste.

To pa ni vse, sledi najtežji del, sicer pravilna nastavitev pom.xml-ja:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.8.1</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.jboss.arquillian.junit</groupId>
    <artifactId>arquillian-junit-container</artifactId>
    <version>1.0.3.Final</version>
    <scope>test</scope>
</dependency>    

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jaxrs</artifactId>
    <version>2.3.4.Final</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jackson-provider</artifactId>
    <version>2.3.4.Final</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.jboss.shrinkwrap.resolver</groupId>
    <artifactId>shrinkwrap-resolver-api-maven</artifactId>
    <version>2.0.0-alpha-1</version>
    <scope>test</scope>
    <type>jar</type>
</dependency>    

<dependency>
    <groupId>org.jboss.shrinkwrap.resolver</groupId>
    <artifactId>shrinkwrap-resolver-impl-maven</artifactId>
    <version>2.0.0-alpha-1</version>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>com.google.collections</groupId>
            <artifactId>google-collections</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Vidimo, da smo na classpath dali naslednje stvari:

  • junit in arquillian container;
  • implementacijo resteasy in jackson;
  • shrinkwrap resolver, katerega si bomo pogledali kasneje.

Dodatno bomo definirali maven profile, v katerem pa imamo naslednjo definicijo:

<profiles>  
    <profile>
        <id>glassfish-managed-3.1</id>
        <dependencies>
            <dependency>
                <groupId>com.inteligoo</groupId>
                <artifactId>intelicommon</artifactId>
                <version>1.0</version>

                <!--
                  Ker spodaj include.dam
                -->
                <exclusions>
                    <exclusion>
                        <groupId>javax</groupId>
                        <artifactId>javaee-api</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.slf4j</groupId>
                        <artifactId>slf4j-api</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>org.slf4j</groupId>
                        <artifactId>slf4j-log4j12</artifactId>
                    </exclusion>
                </exclusions> 
           </dependency>    
           <dependency>
               <groupId>org.jboss.arquillian.container</groupId>
               <artifactId>arquillian-glassfish-managed-3.1</artifactId>
               <version>1.0.0.CR3</version>
               <scope>test</scope>
               <exclusions>
                   <exclusion>
                       <groupId>org.jboss.arquillian.container</groupId>
                       <artifactId>arquillian-container-spi</artifactId>
                   </exclusion>  
                   <exclusion>
                       <groupId>com.sun.jersey</groupId>
                       <artifactId>jersey-bundle</artifactId>
                   </exclusion>
                   <exclusion>
                       <groupId>com.sun.jersey.contribs</groupId>
                       <artifactId>jersey-multipart</artifactId>
                   </exclusion>
             </exclusions>
         </dependency>

         <!--
           Nadomestim z novejsimi, sicer imam error:
org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData.getContexts(Ljava/lang/Class;)Ljava/util/Collection;
         -->
         <dependency>
             <groupId>org.jboss.arquillian.container</groupId>
             <artifactId>arquillian-container-spi</artifactId>
             <version>1.0.3.Final</version>
             <scope>test</scope>
         </dependency>

         <!--
           Nadomestim z novejsimi, sicer imam error:
             com.sun.jersey.api.client.ClientHandlerException:

A message body writer for Java type, class com.sun.jersey.multipart.FormDataMultiPart, and MIME media type, multipart/form-data, wasnot found
          -->       
         <dependency>
             <groupId>com.sun.jersey</groupId>
             <artifactId>jersey-bundle</artifactId>
             <version>1.12</version>
             <scope>test</scope>
         </dependency>

         <dependency>
             <groupId>com.sun.jersey.contribs</groupId>
             <artifactId>jersey-multipart</artifactId>
             <version>1.12</version>
             <scope>test</scope>
         </dependency>      

         <!--
           Sicer mam error:
             Absent Code attribute in method...
         -->
         <dependency>
             <groupId>org.jboss.spec</groupId>
             <artifactId>jboss-javaee-6.0</artifactId>
             <version>1.0.0.Final</version>
             <type>pom</type>
             <scope>provided</scope>
         </dependency>      
     </dependencies>

     <build>
         <testResources>
             <testResource>
                 <directory>src/test/resources</directory>
             </testResource>
             <testResource>
                 <directory>src/test/resources-glassfish-managed</directory>
             </testResource>
         </testResources>
      </build>
   </profile>
</profiles>

POZOR! Obvezno je potrebno podrobno pregledati zgornji odsek kode, namreč v komentarjih so opisani vsi problemi, na katere sem naletel. Zato je potrebno uporabiti tudi nekaj exclusion-ov, da se stvar sploh hoče zagnati.

Priprava testov

Da lahko testiramo našo storitev s RESTEasy, moramo implementirati t.i. razred stub, ki bo samo ogrodje za našo storitev:

@Path("/alert")
public interface TestResourcesClientStub {

    @GET
    @Path("/{id}")
    @Consumes("text/plain")
    @Produces("application/json")
    public AppJmsAlert getAlertById(@PathParam("id") int id);  

}

Ogrodje bomo uporabili v naših testih Arquillian:

@RunWith(Arquillian.class)
@RunAsClient

public class TestResourceTest {   

    private static final String RESOURCE_PREFIX = RestApplication.class.getAnnotation(ApplicationPath.class).value().substring(1);

    /**
    * Resource, ki vrne npr.: http://localhost:8080/test/ v primeru, da deployamo test.war
    * V primeru Glassfish Embeddable, nam ta resource ne vrne prave vrednosti
    */
    @ArquillianResource
    private URL url;

    @Deployment(testable=false)
    public static WebArchive deploy(){   

        //0.) Za dodajanje poljubnih artifaktov iz POMa v obliki knjiznic
        final MavenDependencyResolver resolver = DependencyResolvers.use(MavenDependencyResolver.class);

        //1.) Izdelam arhiv
        WebArchive war = ShrinkWrap.create(WebArchive.class, "test.war");

        //2.) NASTAVITVE
        war.addClasses(SystemConfiguration.class, PuAdminWH.class, RestApplication.class)

        //ENTITETE
           .addPackage(AppJmsAlert.class.getPackage())   
           .addClasses(KpiReportHelper.class, KpiSettings.class)

        //REST CLASSI
           .addClasses(NoResultExceptionMapper.class, TestResource.class)

        //VSE POTREBNE KNJIZNICE: HIBERNATE + JACKSON (pretvorba objektov v JSON)
           .addAsLibraries(resolver.artifacts("org.hibernate:hibernate-core:4.1.0.Final", "org.hibernate:hibernate-entitymanager:4.1.0.Final", "org.jboss.resteasy:resteasy-jackson-provider:2.3.4.Final").resolveAsFiles())

       //BAZA
           .addAsResource("test-persistence.xml", "META-INF/persistence.xml")

       //CDI   
           .addAsWebInfResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml")); 

         return war;  
    }

    /**
    * Inicializacija REST EASY + JACKSON (pretvorba iz JSONa v objekte)
    */
    @BeforeClass
    public static void initResteasyClient() {

        ResteasyProviderFactory instance = ResteasyProviderFactory.getInstance();
        instance.registerProvider(ResteasyJacksonProvider.class);
        RegisterBuiltin.register(instance);
    }

    /**
    * Testiram v primeru, ko mi storitev vrne alert s pričakovanim IDjem
    *
    */
    @Test
    public void testIdExists() {
        int idExists = 490;
        
        //resteasy client
        TestResourcesClientStub client = ProxyFactory.create(TestResourcesClientStub.class,  url.toString() + RESOURCE_PREFIX);

        AppJmsAlert alert = client.getAlertById(idExists);
        Assert.assertEquals(idExists, alert.getIdAppJmsAlert().intValue());

    }

    /**
    * Testiram response storitve, ko alert z določenim idjem ne obstaja
 
    *
    */
    @Test
    public void testBadResponse() {

        int idDoesntExists = 41290;

        //resteasy client
        TestResourcesClientStub client = ProxyFactory.create(TestResourcesClientStub.class,  url.toString() + RESOURCE_PREFIX);

        try {
            AppJmsAlert alert = client.getAlertById(idDoesntExists);
        }
        catch(ClientResponseFailure e) {

            // to je ok
            if(e.getResponse().getResponseStatus().equals(Response.Status.BAD_REQUEST)){
                return;
       }
    }
    Assert.fail("No bad response for id=" + idDoesntExists);
  }
}

Pomebnejše stvari so naslednje:

  • Anotacija @ArquillainResource nam vrne del URLja, na katerem zaganjamo našo testno aplikacijo;
  • RESOURCE_PREFIX nam vrne osnovni del URLja za REST, v našem primeru je to niz po vrednosti “resources”;
  • test bomo izvajali kot odjemalec (@RunAsClient);
  • paket war po imenu “test.war”, v katerem bo naš resurs REST, ki ga testiramo, se izdela s pomočjo Maven Resolverja, ki nam omogoča, da dodamo v naš war vse pakete, neposredno iz maven repozitorija;
  • test-persistance.xml je popolnoma enak persistance.xml, saj namen tega testa ni priprava ustrezne testne baze, ampak bomo uporabili kar obstoječo bazo. Splošno to ne velja in je potrebno pripraviti tudi ustrezno testno bazo;
  • v test.war je potrebno dodati vse razrede, ki jih bomo uporabljali v testu;
  • @BeforeClass anotacija nam označuje metodo, v kateri definiramo odjemalca RESTEasy, s podporo za knjižnico JACKSON;
  • implementirali smo dva testa, sicer v prvem testu pričakujemo, da nam storitev vrne točno določeno entiteto s točno določenim IDjem, v drugem testu pa pričakujemo, da nam storitev vrne BAD_REQUEST, saj poizvedbo pripravimo tako, da namenoma damo napačen id kot parameter.

Pri zagonu našega testa, se tako zgradi paket test.war, se zažene Glassfish 3.1, v katerega se omenjeni paket namesti, in kot odjemalec se zaženeta oba testa. Sami testi niso nič posebnega, najtežji del je žal konfiguracija vseh potrebnih knjižnic (pom.xml), saj privzete knjižnice, kot so navedene na domači strani Arquilliana žal ne delujejo out-of-the-box.

Vidimo tudi, da smo definirali pot do resursov za naše teste (src/test/resources-glassfish-managed) v katerem imamo test-persistance.xml, za našo testno okolje.

Preprosto preskušanje entitete JPA 2 z Netbeans 7 in Maven

Posted on

Java EE 6 je stara dobro leto dni, NetBeans 7 Beta je zunaj že kar nekaj časa, čez dva meseca bo zunaj končna različica, Maven pa pridobiva na priljubljenosti in je dobro integriran v današnje IDE, tudi v Netbeansu. Zato sta tokrat naša cilja naslednja:

  • ustvariti nov projekt Maven s pomočjo Netbeansov, ki bo preskušal na novo ustvarjeno entiteto (JPA2) prek ogrodja JUnit
  • prikazati integracijo med Netbeansi in Mavenom

Uporabili bomo podatkovno bazo PostgreSQL, aplikacijskega strežnika pa za ta namen ne bomo potrebovali. Vse skupaj bomo zaganjali na Windows XP.

Mogoče se kdo sprašuje, kakšen je smisel uporabe JUnit-a nad poljubno entiteto, saj so v njej samo metode tipa setter/getter. Vendar, ker za tovrstno testiranje ne potrebujemo transakcij JTA (torej ne potrebujemo aplikacijskega strežnika) in ker uporabljamo nad podatkovno bazo strategijo “drop and create”, lahko nad obravnavano entiteto brez velikega vložka dela preskušamo vsaj poizvedbe JPQL.

1. Priprava okolja za Maven

Uporabili bomo Apache Maven 3.0.1. Maven je bundlan v Netbeanse, vendar bomo v našem primeru uporabili ločeno inštalacijo. Maven lahko snamete tule: http://maven.apache.org/download.html in ga odpakirate v poljuben direktorij, npr. f:/apache-maven-3.0.1. Pri sami inštalaciji je pomebno to, da nastavimo njegov bin v spremenljivko PATH. Tedaj lahko preverimo, ali je vse v redu:

Po definiciji je Maven rešitev za buildanje projektov (in še veliko več …). Pri svojem delu uporablja datoteko POM – to je datoteka XML, v kateri je opredeljen naš projekt. Projekt običajno potrebuje več t. i. artifaktov – zunanjih modulov, od katerih je odvisen. To so t. i. dependencies, ki so prav tako opredeljene v datoteki POM. Ker je tudi sam projekt nek artifakt, rečemo, da je Maven orodje za upravljanje artifaktov.

Artifakti se sprva nahajajo v oddaljenih repozitorijih in se med buildanjem projekta običajno  prenesejo v lokalni repozitorij. Zato Maven potrebuje tudi povezavo do spleta. Privzeta nastavitev za lokalni repozitorij je /Documents and Settings/User/.m2/repository. Ta je v tem trenutku še prazen.

Ker Mavena ne bomo uporabljali command line, moramo v Netbeansih nastaviti določene parametre. Znotraj Tools => Options => Miscellaneous, zavihek Maven, nastavimo pot do nameščenega Mavena in pot do lokalnega repozitorija:

2. Priprava podatkovne baze

Uporabili bomo PostgreSql, kjer bomo ustvarili novo podatkovno bazo po imenu MyAppTest. Test smo dali v ime zato, ker bomo ob zaganjanju aplikacije v tej bazi sproti brisali in ustvarjali tabele.

3. Ustvarjanje projekta

Gremo v Netbeanse in izberemo New Project, kjer potem izberemo Maven => Java Application.

Nato izpolnimo naslednje parametre:

Tako ustvarimo nov projekt  glede na archetype: maven-archetype-quickstart:1.1. Prav tako se v lokalni repozitorij naloži nekaj osnovnih potrebnih modulov (npr. maven plugin api). Sedaj smo dobili osnovno strukturo projekta:

Vidimo, da je projekt razdeljen na več delov: del, v katerem so izvorne datoteke, del v katerem so testi, del za (Test) Dependencies in del za datoteko POM, ki v tem trenutku vsebuje naslednje:

<groupId>blog.milanpevec</groupId>
 <artifactId>MyApp</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>MyApp</name>
 <url>http://maven.apache.org</url>

 <properties>
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

 <dependencies>
   <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.8.2</version>
     <scope>test</scope>
   </dependency>
 </dependencies>

Vidimo, da je edini artifakt junit, namreč ta modul bomo potrebovali za preskušanje. Dodatno pri artifaktu popravimo različico na vrednost 4.8.2, kajti Netbeansi kot privzeto uporabljajo različico 3.

Zaradi uporabe JPA2 dodamo v datoteko še naslednje vrstice:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.3.2</version>
      <inherited>true</inherited>
      <configuration>
        <source>1.6</source>
        <target>1.6</target>
      </configuration>
    </plugin>
  </plugins>
</build>

S tem povemo, naj Maven v življenjskem ciklu prevajanja (compile) uporabi plugin za prevajanje Java SE različice 1.6. V nasprotnem bi se nam kasneje pri delu z JPA2 pojavljala opozorila.

4. Izdelava entitete JPA2

Izberemo File => New => Persistance => Entity Class. Obrazec izpolnimo z naslednjimi podatki:

Nastavili smo, da se entiteta po imenu Auser ustvari znotraj paketa blog.milanpevec.entities. Ostalo smo pustili privzeto. Pomembno je to, da spodaj obkljukamo “Create Persistance Unit”, da lahko v naslednjem koraku hkrati opredelimo še PU:

Za t. i. persistance providerja izberemo EclipseLink, izberemo novo povezavo do baze (ali jo ustvarimo, če je še nimamo) in izberemo strategijo “Drop and Create”, saj hočemo, da se ob preskušanju vedno pobriše shema in se na novo ustvarijo bazni objekti.

Zaradi integracije Mavena z Netbeansi so sedaj v datoteki POM samodejno opredeljeni novi artifakti, od katerih je odvisen naš projekt:

<dependency>
 <groupId>org.eclipse.persistence</groupId>
 <artifactId>eclipselink</artifactId>
 <version>2.2.0-M4</version>
</dependency>
<dependency>
 <groupId>org.eclipse.persistence</groupId>
 <artifactId>javax.persistence</artifactId>
 <version>2.0.0</version>
</dependency>

Gre za dva artifakta, ki sta uvrščena v isto skupino (org.eclipse.persistance). Artifakt Eclipselink je definiran zaradi PU, javax.persistance pa zaradi entitete JPA2. Ker bo PU uporabljal JDBC, moramo tudi zanj dodati artifakt:

<dependency>
 <groupId>postgresql</groupId>
 <artifactId>postgresql</artifactId>
 <version>9.0-801.jdbc4</version>
</dependency>

Ker omenjenih artifaktov še nimamo v lokalnem repozitoriju, nam Netbeansi prikažejo opozorila:

Zgornje lahko rešimo na več načinov. Lahko bi sprožili build in bi nam takrat naložilo vse potrebne artifakte. Lahko pa iz kontekstnega menija našega projekta izberemo “Show and resolve problems”, “Download Dependencies”:

Vendar je pred tem treba povedati, kje v oddaljenem repozitoriju se nahaja artifakt eclipselink. Netbeansi nam v datoteko POM privzeto nastavijo naslednje:

<repositories>
 <repository>
   <url>ftp://ftp.ing.umu.se/mirror/eclipse/rt/eclipselink/maven.repo</url>
   <id>eclipselink</id>
   <layout>default</layout>
   <name>Repository for library Library[eclipselink]</name>
 </repository>
</repositories>

Toda zaradi FTP-ja lahko pride do težave. Zato zgornjo vrstico nadomestimo z naslednjim:

<url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo</url&gt;

Sedaj Netbeansi sami naložijo manjkajoče artifakte v lokalni repozitorij.

Da bi bilo lažje slediti, kaj se dogaja med postopkom preskušanja, dodamo v PU novo lastnost (znotraj datoteke persistance.xml). Želimo, da se nam izpisujejo vse poizvedbe nad bazo. Zato dodamo lastnost eclipselink.logging.level z vrednostjo FINE:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
 <persistence-unit name="blog.milanpevec_MyApp_PU" transaction-type="RESOURCE_LOCAL">
   <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
   <class>blog.milanpevec.entities.Auser</class>
   <properties>
     <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/MyAppTest"/>
     <property name="javax.persistence.jdbc.password" value="postgres"/>
     <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
     <property name="javax.persistence.jdbc.user" value="postgres"/>
     <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
     <property name="eclipselink.logging.level" value="FINE"/>
   </properties>
 </persistence-unit>
</persistence>

Iz zgornjega je razvidno, da bomo uporabili transakcije RESOURSE_LOCAL, saj bomo preskušanje zaganjali mimo aplikacijskega strežnika.

Pozor! EclipseLink potrebuje eksplicitno določena imena entitet, s katerimi upravlja, zato moramo dodati zgoraj znotraj <class> še ime entitete. V nasprotnem primeru dobimo “JPA exception: Object: … is not a known entity type.”

5. Izdelava testa

Najprej v našo entiteto dodamo dve lastnosti: firstname in lastname ter določimo, da primarni ključ tabele določa sekvenca auser_id_auser_seq. Prav tako opredelimo t. i. named query, ki poišče vse entitete Auser v podatkovni bazi. To poizvedbo bomo kasneje tudi preskusili.

@Entity
@NamedQuery(name=Auser.findAll,query="SELECT a FROM Auser a")
public class Auser implements Serializable {

 public final static String findAll = "entities.Message.findAll";    
 private static final long serialVersionUID = 1L;

 @Id
 @GeneratedValue(generator = "ContSeq")
 @SequenceGenerator(name = "ContSeq", sequenceName = "auser_id_auser_seq", allocationSize = 1)   
 private Long id;    
 private String firstname;    
 private String lastname;
 
 public Long getId() {
   return id;
 }
 public void setId(Long id) {
   this.id = id;
 }    
 public String getFirstname() {
   return firstname;
 }
 public void setFirstname(String firstname) {
   this.firstname = firstname;
 }
 public String getLastname() {
   return lastname;
 }
 public void setLastname(String lastname) {
   this.lastname = lastname;
 }
}

Sedaj pa si poglejmo, kako bomo sestavili test za našo entiteto. Napisali bomo testno metodo (anotacija @Test), ki se zažene samodejno zaradi omenjene anotacije. Znotraj nje bomo preskusili shranjevanje entitete v podatkovno bazo in edino opredeljeno poizvedbo. Uporabili bomo fixture @Before, ki označuje metodo, ki se zažene pred vsakim testom. V njej bomo implementirali pridobivanje trenutne transakcije. Dodatno bomo uporabili fixture @BeforeClass in @AfterClass, s katerim bomo ustvarili in zaprli naš EntityManager:

public class AuserTest  {
 
 private static EntityManagerFactory emf; 
 private static EntityManager em; 
 private static EntityTransaction tx; 
 
 @BeforeClass 
 public static void initEntityManager() throws Exception { 
   emf = Persistence.createEntityManagerFactory("blog.milanpevec_MyApp_PU"); 
   em = emf.createEntityManager(); 
 } 
 
 @AfterClass 
 public static void closeEntityManager() throws SQLException { 
   em.close(); 
   emf.close(); 
 } 
 
 @Before 
 public void initTransaction() { 
   tx = em.getTransaction(); 
 } 
 
 @Test 
 public void createAuser() throws Exception { 
 
   // Creates an instance of auser
   Auser auser = new Auser(); 
   auser.setFirstname("Janez");
   auser.setLastname("Novak"); 
 
   // Persists the auser to the database 
   tx.begin();  
   em.persist(auser); 
   tx.commit(); 
   assertNotNull("ID should not be null", auser.getId()); 
 
   // Retrieves all users from the database 
   List<Auser> ausers = em.createNamedQuery(Auser.findAllAusers).getResultList(); 
   assertEquals(1, ausers.size()); 
 } 
}

Uspešno izvedeno preskušanje ima naslednji izhod:

Zgoraj smo tako pokazali, da je mogoče zelo hitro in preprosto pripraviti okolje za preskušanje entitet. Če bi kdo želel celotno kodo projekta, mi lahko piše. Do naslednjič …