7 Replies Latest reply on Sep 13, 2008 3:34 AM by amit.u.purohit

    Using testNG with Seam

    amit.u.purohit
      Hi

      I am working on JBOSS 4.3, seam-2.0.2.SP1 on eclipse IDE. I am trying to unit test my application using the TESTNG plugin. However, I get a null pointer exception on the fields/context parameters injected using the Seam annotations,
      Please, let me know what am I doing wrong here..
      example code
      Seam component

      @Stateful
      @Name("S_Movie_Service")
      public class MovieService {
             
              @In(create=true)
              @Out(required=false)
              Movie S_Movies;
             
              @In(create=true)
              MovieHome S_Movie_Home ;
             
              @Logger
              private Log log;
             
              public List<Movie> getAllMovies() throws CrbException{
                      try{
                              log.debug("Getting movie information for all the movies");
                              return (CrbUtil.getMovieList(S_Movie_Home.getAllMovies(entityManager)));
                      }catch(CrbException ce){
                              log.error("Error occured while retreving all the movies : #0 ", ce.getMessage());
                              throw new CrbException("Error occured while retreving all the movies",ce);
                      }catch(Exception e){
                              log.error("Uncaught exception was caught while retreiving all the movies : #0 ", e.getMessage());
                              e.printStackTrace();
                              throw new CrbException("Uncaught exception was caught while retreiving all the movies",e);
                      }
              }
      }

      here is my TestNG class

      public class MovieServiceTest extends BaseServiceTest{
             
              MovieHome movieHome = new MovieHome();
             
              CacheLoader S_CacheLoader = new CacheLoader();
             
              @Test
              public void testGetAllMovies(){
                      boolean pass = true;
                      List<Movie> lstMovies;
                      EntityManager entityManager = getEntityManager();
                      IMovieService movieService = new MovieService();
                      try{
                              initialiseCache(S_CacheLoader);
                              movieService.setCrbDatabase(entityManager);
                              entityManager.getTransaction().begin();
                              lstMovies = movieService.getAllMovies();
                              //Print the movie details
                              for(Movie movie : lstMovies){
                                      //Display the movie information
                                     
                              }
                              assert (lstMovies.size() != 0);
                              //Commit the transaction
                              entityManager.getTransaction().commit();
                              entityManager.close();
                                     
                      }catch(CrbException ce){
                              pass = false;
                      }
                      catch(Exception e){
                              pass = false;
                      }finally{
                              assert pass;
                      }
              }
      }

      When I run my above test case, I get a null pointer exception on       
      log.debug("Getting movie information for all the movies");
      suggesting that the logger has not been initialised. Same is the error for other properties injected using Seamannotations @IN
      can you suggest me how can I inject the dependencies at run time through my testNG class
        • 1. Re: Using testNG with Seam
          dhinojosa

          Are you talking about Integration Testing?


          • 2. Re: Using testNG with Seam
            amit.u.purohit

            Thanks for the reply
            I am writing the services, which would be consumed by an external UI layer. The test cases I have mentioned in my example are the Unit test cases for testing my services.

            • 3. Re: Using testNG with Seam

              In your test, your MovieService object is being created using new, but its creation should be handled by Seam IoC not by new:


               IMovieService movieService = new MovieService();
              



              Please read Chapter 31. Testing Seam applications


              Regards,

              • 4. Re: Using testNG with Seam
                amit.u.purohit

                If I inject my services or any components using the SEAM IoC/Bijection framework, I get a Null Pointer exception, on trying to call any members of the corresponding components.
                I looked at the example, you have suggested and the  test class in the ezample is also creating an isntance of the Seam component using the new() constructor, and does not use the Seam IoC framework

                • 5. Re: Using testNG with Seam
                  dhinojosa

                  Well if you are unit testing, you need to provide your own logger or a mock of the logger, and annotations don't matter in a unit testing environment since you are not integrating with a server.

                  • 6. Re: Using testNG with Seam

                    Hi!


                    I guess you didn't carefully read all the 31 chapter, in paragraph after the first test example you can read:



                    You'll notice we aren't testing retrieving data from or persisting data to the database; nor are we testing any functionality provided by Seam.


                    It is only testing the calculateTotal method, and that method doesnt need any injection to work.


                    If you continue reading, in 31.2. Integration testing Seam components you will find an example that does test using injection, and in 31.3. Integration testing Seam application user interactions you can even see examples that test interaction.


                    Regards,

                    • 7. Re: Using testNG with Seam
                      amit.u.purohit
                      Thanks for the reply.
                      I could test most of my services using the examples provided in the Seam documentation.
                      However, I have a requirement, wherein my database services would accept a movie object and persist it as shown below

                           public void persistMovieObj(Movie movie) {
                                try{
                                     log.debug("Persisting movie information for the movie : " + movie.getTitle() );
                                     entityManager.persist(movie);
                                }catch(Exception e){
                                     log.error("Unhandled exception was caught while persisting movie : " + movie.getTitle() );
                                }
                           }






                      my test method is as shown below:

                      @Test
                           public void testPersistMovie() throws Exception{
                                new FacesRequest() {
                                     
                                @Override
                                    protected void invokeApplication()
                                    {
                                           boolean pass = true;
                                           try{
                                                Movie movie =(Movie)Component.getInstance(Movie.class, create);
                                                movie.setTitle("Movie1");
                                                invokeMethod("#{S_Movie_Service.persistMovieObj(movie)}");
                                           }catch(Exception e){
                                               log.error("Error occured " + e.getMessage());
                                               e.printStackTrace();
                                               pass = false;
                                           }finally{
                                                assert pass;
                                           }
                                          
                                    }
                                   
                                 }.run();
                           }

                      The above method doest not seem to pass the movie object to the services layer and hence I get a null movie object when I try to persist the movie

                      Can you please tell me what I am doing wrong or the changes to be made in the code ?
                      Help Really Appreciated