11 Replies Latest reply on Feb 28, 2018 2:22 AM by mkouba

    Help Bootstrapping StrutsTestCase in Junit

    gbuckholtz

      I have struts2 running with it's CDI-plugin and Weld is the CDI container of choice on my glassfish server. 

       

      For unit testing struts Actions, Struts has a StrutsTestCase http://struts.apache.org/maven/struts2-plugins/struts2-junit-plugin/apidocs/org/apache/struts2/StrutsTestCase.html

       

      The catch with struts is that it uses a JNDI lookup to find the weld context to override its internal injection framework (Which is a distant ancestor or Weld!).  I am trying to mock an InitialContextFactory so when struts tries to look up java:app/BeanManager  the mock will provide a BeanManager instance.  My problem is getting a BeanManager out of the Junit4 WeldInitiator. 

       

      tl;dr How do you get a BeanManager instance in Junit4?

        • 1. Re: Help Bootstrapping StrutsTestCase in Junit
          mkouba

          Hi Glenn,

          in Weld SE you can obtain the BeanManager using e.g. org.jboss.weld.environment.se.WeldContainer.current().getBeanManager(), or even in a portable way: CDI.current().getBeanManager().

          • 2. Re: Help Bootstrapping StrutsTestCase in Junit
            gbuckholtz

            That's what I am hoping to do.   The thing I can't get is a running weld container.

             

            I think I have narrowed it down to the test fixture I am using for struts.   The StrutsTestCase extends TestCase,  the junit3 way of doing things.   That means junit annotations don't work.   The @rule for starting weld using the WeldInitiator won’t work because it relies on its apply method to be called to complete creation of the weld container. 

             

            I am going to modify the StrutsTestCase that came with Struts and make it  Junit4 (don’t extend TestCase)  and put in the appropriate annotations and hopefully that will work!

             

            If I am completely wrong about this and there is an easier way to get a weld container I would love to know. 

             

            Thanks for the quick reply!

            • 3. Re: Help Bootstrapping StrutsTestCase in Junit
              mkouba

              I see. Well, weld-junit only supports JUnit 4 and JUnit 5. However, you can use Weld SE programmatic bootstrap API to start/stop the container: Chapter 17. Application servers and environments supported by Weld.

              1 of 1 people found this helpful
              • 4. Re: Help Bootstrapping StrutsTestCase in Junit
                gbuckholtz

                Thanks for the link! 

                 

                I will give that a try first.

                 

                I have an ejb in my test.  Is it going to be a problem if I don’t use the WebInitiator will I be able to attach the EJB factory?

                • 5. Re: Help Bootstrapping StrutsTestCase in Junit
                  mkouba

                  If you don't use weld-unit you would have to implement your own EjbInjectionServices in order to be able to resolve @EJB injection points, e.g. something like weld-junit/MockEjbInjectionServices.java at master · weld/weld-junit · GitHub and register it e.g. through org.jboss.weld.environment.se.Weld.addServices().

                  • 6. Re: Help Bootstrapping StrutsTestCase in Junit
                    gbuckholtz

                    Sounds like it is going to be easier to modify the Struts Junit base class.  I tried your suggestion of creating an instance of Weld and then getting a container from the initialize method.  It ended up failing with a Java lang error: Enclosing method not found.

                    Also I believe the default behaviour of weld is to crawl the whole class path looking for injection points.  It was taking a crazy long time looking and was spitting out tons of ClassNotFoundExceptions. 

                     

                    If my Junit thing doesn’t work I will try your latest suggestion. 

                     

                    Thanks for your help!

                    • 7. Re: Help Bootstrapping StrutsTestCase in Junit
                      gbuckholtz

                      I know this is more of a Junit question but it pertains to weld-unit.  Do you know then the apply() method is called in the @Rule lifecycle?  I have made my StrutsTestCase to be Junit4 by not extending TestCase and putting in the appropriate annotations.

                      • 8. Re: Help Bootstrapping StrutsTestCase in Junit
                        gbuckholtz

                        I have constructed this rule:

                         

                            @Rule

                            public WeldInitiator weld4 = WeldInitiator.from(WeldInitiator.createWeld()).setEjbFactory(ip -> new MockInstructorSessionBean()).build()

                         

                        I am hoping it is saying:

                         

                        Create a Weld instance

                        Set the EJB factory to be MockInstructorSessionBean

                        Build me a WeldInitiator with these settings.

                         

                        I am getting  WELD-ENV-002009: Weld SE container cannot be initialized - no bean archives found  which I can see because I have not asked for a specific bean to Inject and there is no jar file to parse for injection points. 

                         

                        Is there a better way to get the WeldInitiator? Once I get the WeldInitiator then I can do the getBeanManager().

                        1 of 1 people found this helpful
                        • 9. Re: Help Bootstrapping StrutsTestCase in Junit
                          mkouba

                          Well, this error simply states that there are no bean archives found and thus no bean definitions available. In other words, it does not make sense to start the CDI container at all. You need to specify what beans should be tested, i.e. available from the BeanManager. By default, WeldInitiator does not perform the automatic bean discovery. Instead, only specific bean classes (classes under the test) are considered. E.g. WeldInitiator.from(FooCDIBean.class).setEjbFactory(ip -> new MockInstructorSessionBean()).build().

                          1 of 1 people found this helpful
                          • 10. Re: Help Bootstrapping StrutsTestCase in Junit
                            gbuckholtz

                            Thanks so much for your help Martin! 

                             

                            I was able to get my unit test to create a struts2 action.  After I got the WeldInitiator started I included the test class using .inject(this),  and was able to simply inject the BeanManager!  Worked like a charm!  My mock InitialContext just spit that BeanManager out when asked for the CDI JNDI resource.  Then Struts2 was able to plug that BeanManager in as its injection engine. 

                            • 11. Re: Help Bootstrapping StrutsTestCase in Junit
                              mkouba

                              I'm glad it works for you!