13 Replies Latest reply on Sep 20, 2011 11:52 AM by pedrokowalski

    Test modified test enrichment

    pedrokowalski

      Howdy!

       

      I've made some changes to the EJB test enrichment and would like to use it (test it on my own project). Normally I used the Alpha-5 version from maven dependencies.

       

      Should it be enought to add additional maven dependency which explicitely says that EJB test enrichment module should be resolved in 1.0.0.Final-SNAPSHOT version or should I modify some other dependency as well?

       

      After I successfully build whole arquillian-core project, how can I point my own project to use this freshly build version? (what dependency should I define)?

       

      Thanks in advance!

       

      Cheers!

        • 1. Re: Test modified test enrichment
          aslak

          If you use dependencyManagment and import the arquillian-bom in the version you want, 1.0.0.Final-SNAPSHOT, it will override the versions defined by the container adaptor.

           

          https://gist.github.com/1154075

          • 2. Re: Test modified test enrichment
            pedrokowalski

            Thanks Aslak!

             

            Unforunately, right now I have different problem when running the test:

             

            java.lang.NoClassDefFoundError: org/jboss/shrinkwrap/descriptor/impl/base/NodeProviderImplBase

                at java.lang.ClassLoader.defineClass1(Native Method)

                at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)

                at java.lang.ClassLoader.defineClass(ClassLoader.java:615)

                at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)

                at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)

                at java.net.URLClassLoader.access$000(URLClassLoader.java:58)

                at java.net.URLClassLoader$1.run(URLClassLoader.java:197)

                at java.security.AccessController.doPrivileged(Native Method)

                at java.net.URLClassLoader.findClass(URLClassLoader.java:190)

                at java.lang.ClassLoader.loadClass(ClassLoader.java:306)

                at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)

                at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

                at java.lang.Class.forName0(Native Method)

                at java.lang.Class.forName(Class.java:247)

                at org.jboss.shrinkwrap.descriptor.api.DescriptorConstructionInfo.<init>(DescriptorConstructionInfo.java:69)

                at org.jboss.shrinkwrap.descriptor.api.DescriptorInstantiator.getDescriptorConstructionInfoForUserView(DescriptorInstantiator.java:275)

                at org.jboss.shrinkwrap.descriptor.api.DescriptorInstantiator.createImporterFromUserView(DescriptorInstantiator.java:178)

                at org.jboss.shrinkwrap.descriptor.api.Descriptors.importAs(Descriptors.java:108)

                at org.jboss.shrinkwrap.descriptor.api.Descriptors.importAs(Descriptors.java:85)

                at org.jboss.arquillian.impl.bootstrap.ConfigurationRegistrar.loadConfiguration(ConfigurationRegistrar.java:50)

                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

                at java.lang.reflect.Method.invoke(Method.java:597)

                at org.jboss.arquillian.impl.core.ObserverImpl.invoke(ObserverImpl.java:90)

                at org.jboss.arquillian.impl.core.EventContextImpl.invokeObservers(EventContextImpl.java:98)

                at org.jboss.arquillian.impl.core.EventContextImpl.proceed(EventContextImpl.java:80)

                at org.jboss.arquillian.impl.core.ManagerImpl.fire(ManagerImpl.java:126)

                at org.jboss.arquillian.impl.core.ManagerImpl.fire(ManagerImpl.java:106)

                at org.jboss.arquillian.impl.core.ManagerImpl.<init>(ManagerImpl.java:91)

                at org.jboss.arquillian.impl.core.ManagerBuilder.create(ManagerBuilder.java:74)

                at org.jboss.arquillian.impl.DeployableTestBuilder.build(DeployableTestBuilder.java:97)

                at org.jboss.arquillian.impl.DeployableTestBuilder.build(DeployableTestBuilder.java:67)

                at org.jboss.arquillian.junit.Arquillian.<init>(Arquillian.java:82)

                at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

                at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)

                at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)

                at java.lang.reflect.Constructor.newInstance(Constructor.java:513)

                at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:31)

                at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)

                at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)

                at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)

                at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)

                at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)

                at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)

                at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)

                at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)

                at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)

                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452)

                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)

                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)

                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

            Caused by: java.lang.ClassNotFoundException: org.jboss.shrinkwrap.descriptor.impl.base.NodeProviderImplBase

                at java.net.URLClassLoader$1.run(URLClassLoader.java:202)

                at java.security.AccessController.doPrivileged(Native Method)

                at java.net.URLClassLoader.findClass(URLClassLoader.java:190)

                at java.lang.ClassLoader.loadClass(ClassLoader.java:306)

                at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)

                at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

                ... 52 more

             

             

            I'm using the GF-3.1 connector as follows:

             

            <dependency>
            <groupId>org.jboss.arquillian.container</groupId>
            <artifactId>arquillian-glassfish-remote-3.1</artifactId>
            <version>1.0.0.Alpha5</version>
            <scope>test</scope>
            </dependency>

             

            Any ideas? <confused>

            • 3. Re: Test modified test enrichment
              aslak

              You need to update the GlassFish Container version as well. a few changes between Alpha5 and Current Master API/SPIs.

               

              1.0.0.CR1 should do

              • 4. Re: Test modified test enrichment
                pedrokowalski

                Ok, I'll build that right away.

                 

                By the way - (a type of note to my future self ;-)

                I seems that to pass the Servlet 2.5/3.0 Arquillian protocol test, you can't have your own server running at 8080. It failed for me but when I killed it (Glassfish on 8080), the tests passed fine.

                • 5. Re: Test modified test enrichment
                  pedrokowalski

                  I'm still ending with the same ClassNotFoundException...

                   

                  dependencies:

                   

                  <dependency>
                  <groupId>org.jboss.arquillian.container</groupId>
                  <artifactId>arquillian-glassfish-remote-3.1</artifactId>
                  <version>1.0.0.CR1</version>
                  <scope>test</scope>
                  </dependency>
                  <dependency>
                  <groupId>org.jboss.arquillian</groupId>
                  <artifactId>arquillian-junit</artifactId>
                  <version>1.0.0.Alpha5</version>
                  <scope>test</scope>
                  </dependency>

                   

                  dependencyManagement:

                   

                  <dependencyManagement>
                  <dependencies>
                  <dependency>
                  <groupId>org.jboss.arquillian</groupId>
                  <artifactId>arquillian-bom</artifactId>
                  <version>1.0.0.Final-SNAPSHOT</version>
                  <scope>import</scope>
                  <type>pom</type>
                  </dependency>
                  </dependencies>
                  </dependencyManagement>
                  • 6. Re: Test modified test enrichment
                    aslak

                    Replace the arquillian-junit 1.0.0.Alpha5 dep with:

                     

                    org.jboss.arquillian.junit:arquillian-junit-container

                     

                    (without a specific version, it's version is managed via the arq-bom import)

                    • 7. Re: Test modified test enrichment
                      pedrokowalski

                      Once again thanks Aslak. This pushes me towards (btw - was I using some old approach, old artifacts or what?)

                       

                      Right now I got NPE's and if I inspect the enrich(Object) method of EJB enricher I found out that:

                       

                      public void enrich(Object testCase) {

                              if (SecurityActions.isClassPresent(ANNOTATION_NAME)     // This is TRUE

                                      && contextInst.get() != null) {     // This is FALSE

                                  injectClass(testCase);     // enrichment doesn't occur

                              }

                          }

                      Do you have an idea what can be the reason that the Context is not injected by the CDI?

                       

                      TIA.

                       

                      PS: Oh, wait a minute. The Instance and @Inject are not from the CDI but from the Arquillian itself?

                      • 8. Re: Test modified test enrichment
                        aslak

                        right, your running into this issue: https://issues.jboss.org/browse/ARQ-543

                         

                         

                        It's fixed upstream but not released yet. The fix is to add a dependency to org.jboss.arquillian.testenricher:arquillian-testenricher-initialcontext (exposed in arq-bom as well, so no version needed)

                        • 9. Re: Test modified test enrichment
                          pedrokowalski

                          Ah remarkable!

                           

                          Now, let's proceed further ;-)

                          • 10. Re: Test modified test enrichment
                            pedrokowalski

                            Ok, now I've bumped into another thing... kinda weird thing... I mean take a look at this injectClass(Object) method:

                             

                            for (Field field : annotatedFields) {

                                            if (field.get(testCase) == null) // only try to lookup fields

                                                                                // that are not already set

                                            {

                                                EJB fieldAnnotation = (EJB) field

                                                        .getAnnotation(ejbAnnotation);

                                                try {

                                                    String[] jndiNames = resolveJNDIName(field.getType(),

                                                            fieldAnnotation.mappedName(),

                                                            fieldAnnotation.beanName());

                                                    Object ejb = lookupEJB(jndiNames);

                                                    field.set(testCase, ejb);

                                                } catch (Exception e) {

                                                    log.fine("Could not lookup "

                                                            + fieldAnnotation

                                                            + ", other Enrichers might, move on. Exception: "

                                                            + e.getMessage());

                                                }

                                            }

                                        }

                            At this particular case the exception is thrown from the resolveJNDIName(-) method which is the correct behavior - the catch block catches it. The field.set(-) is NOT invoked.

                            However in the test class, the field IS initialized and has a VALID value <confused>. Is it possible that the field value is set by another enricher (don't know how THAT would be possible) or that it's set in some other magical way?

                             

                            The test should go red, but it goes green and it frustrates me even more than the other way around :-)

                             

                            Cheers!

                            • 11. Re: Test modified test enrichment
                              pedrokowalski

                              Ok, some more investigation reveals more details.

                               

                              If I remove the empty beans.xml from the deployment then the EJB enricher works fine. By fine I means that the field is NOT set (according to above post). If I turn back the beans.xml file, the field IS set which is not the appropriate bahavior - the ejb should set this field, not CDI.

                               

                              I don't have any @Inject annotated fields - just a @Produces annotated method which produces different object than the one injected with @EJB.

                               

                              To put the words into code:

                               

                              EJB Enricher:

                              protected void injectClass(Object testCase) {

                                      try {

                                          @SuppressWarnings("unchecked")

                                          Class<? extends Annotation> ejbAnnotation = (Class<? extends Annotation>) SecurityActions

                                                  .getThreadContextClassLoader().loadClass(ANNOTATION_NAME);

                               

                                          List<Field> annotatedFields = SecurityActions

                                                  .getFieldsWithAnnotation(testCase.getClass(), ejbAnnotation);

                               

                                          for (Field field : annotatedFields) {
                                             // THIS SHOWS THE FIELD TO BE SET. SO IT MUST BE SET BY SOMETHING ELSE EVEN BEFORE THE EJB ENRICHER WORKS.

                                              if (field.get(testCase) == null) // only try to lookup fields

                                                                                  // that are not already set

                                              {

                               

                              Is it possible that right now when one field can be managed by different enrichers, the CDI comes in the way and screws this up?

                              • 12. Re: Test modified test enrichment
                                aslak

                                Well, CDI can handle both @EJB, @Resource, @PersistenceContext and @Inject. The CDI injector uses the BeanManager that has access to the internals of the server to do the injection, as a Non Contextual Bean. This will behave more like how the actual injection is suppose to work.

                                 

                                The EJB enricher on the other hand, is a bit of a hack for non CDI based deployments. For pure @EJB injection we try a couple of known patterns / let you define the mappedName to use.

                                • 13. Re: Test modified test enrichment
                                  pedrokowalski

                                  Ok, so I wonder - should the CDI go into action if I use not a simple @EJB annotation but @EJB with some attributes set (mappedName / beanName)?

                                   

                                  I'm aware just of the basics of the CDI magic, but how does it know what bean implementation to inject? Is it EJB-attributes-aware while doing the injection?

                                   

                                  Cheers!