2 Replies Latest reply on Aug 29, 2013 10:08 AM by jrhite_boss

    How to get test helper code properly injected

    jrhite_boss

      I'm using maven and Arquillian to run tests in a JBoss container.

       

      I have a test which works fine...

      @RunWith(Arquillian.class)

      public class UserAccessTest extends DatabaseTest { 

        @Inject UserAccess userAccess;

        @Inject SiteAccess siteAccess;

       

        @Test

        public void newUser() {

          String serverName = randomAlphanumeric(12);

          Site site = new SiteBuilder().withServerName(serverName).build();

         

          Site persistedSite = siteAccess.createSite(site);

       

       

          String email = randomEmail();

          String password = randomAlphanumeric(12);

          User user = new UserBuilder().withEmail(email)

                                                        .withPassword(password)

                                                        .withSite(persistedSite)

                                                        .build();

       

          userAccess.createUser(user);

          User persistedUser = userAccess.getUserByEmail(email);

       

          assertNewEntity(persistedUser);

          assertUsersEqual(user, persistedUser);

        }

       

      but this is a User test, not a Site test, so I'd very much like to remove details about creating and peristing a Site. To do this I've written a SitePersistentBuiilder class which extends an autogenerated SiteBuilder class (using @GeneratePojoBuilder) and adds a single persist method. The SitePersistentBuiilderclass lives in a package under src/java/test.

       

       

      @Stateless

      public class SitePersistentBuilder extends SiteBuilder {

                @Inject SiteAccess siteAccess;

       

                public Site persist() {

                          return siteAccess.createSite(build());

                }

      }

       

      Now I can just change my test to:

       

       

      @RunWith(Arquillian.class)

      public class UserAccessTest extends DatabaseTest { 

        @Inject UserAccess userAccess;

       

        @Test

        public void newUser() {

          String serverName = randomAlphanumeric(12);

          Site site = ((SitePersistentBuilder) new SitePersistentBuilder().withServerName(serverName)).persist();

       

          String email = randomEmail();

          String password = randomAlphanumeric(12);

          User user = new UserBuilder().withEmail(email)

                                                        .withPassword(password)

                                                        .withSite(site)

                                                        .build();

       

          userAccess.createUser(user);

          User persistedUser = userAccess.getUserByEmail(email);

       

          assertNewEntity(persistedUser);

          assertUsersEqual(user, persistedUser);

        }

       

       

      Eliminating many details about site creation and peristence (admittedly in this trivial example it doesn't seem like much).

       

      The problem is my SitePersistentBuilder class doesn't get injected with SiteAccess. What is wrong with this example?

       

      Also more generally, is this a test pattern that seems reasonable? At some point I've eventually like to create persistent test data by using something like:

       

      @UsingDataSet("datasets/sites.yml")

       

      But I still feel like having persistent entity builders in addition to (non-persistent) entity builders will come in handy.

       

      Thanks.

        • 1. Re: How to get test helper code properly injected
          bmajsak

          Hi,

           

          what do you exactly mean by "SitePersistentBuilder is not injected"? I see you are instantiating the object by hand, so there is no injection involved. Are you getting some exceptions while running the test? How does your @Deployment method look like?

           

          With regards to general question - I believe both approaches have benefits and builders are definitely handy especially considering that they can introduce some sort of DSL for the test fixtures and are definitely more refactoring friendly. I have support for this approach in APE in my looooong backlog

           

          Cheers,

          Bartosz

          1 of 1 people found this helpful
          • 2. Re: How to get test helper code properly injected
            jrhite_boss

            Thanks for your reply.

             

            You are absolutely correct and that was a silly oversight of mine. I'm manually instantiating the SitePersistentBuilder class so of course it's not getting injected...duh! :-)

             

            I guess to build on this question to make this more useful, is that it would be nice to define a 'test pattern' of sorts for this SitePersistentBuilder (or any *PersistentBuilder). Basically to make the code I have work I'd probably have to change it from:

             

            <snip>
            @Inject
            UserAccess userAccess;

             

            @Test

            public void newUser() {

                String serverName = randomAlphanumeric(12);

                Site site = ((SitePersistentBuilder) new SitePersistentBuilder().withServerName(serverName)).persist();


                ....

            </snip>

             

            to something more like:

             

            <snip>
            @Inject
            UserAccess userAccess;

            @Inject SitePersistentBuilder sitePersistentBuilder;


            @Test

            public void newUser() {

               String serverName = randomAlphanumeric(12);

               Site site = sitePersistentBuilder.withServerName(serverName)).persist();

             

              

               String email = randomEmail();

               String password = randomAlphanumeric(12);

               User user = new UserBuilder().withEmail(email)

                                                           .withPassword(password)

                                                           .withSite(site)

                                                           .build();

             

                userAccess.createUser(user);

             

                ....

            </snip>

             

            And as far as the SitePersistentBuilder class is concerned I think it is enough that it has an @Inject tag inside of it to trigger CDI management of it as a bean. (ie: I don't need to annotate the SitePersistentBuilder class with @Stateless, or any other annotation)

             

            What might even be cooler and clean up the code even more would be to have SitePersistentBuilder be a (persistent) @Producer of Site instances. So then I wouldn't even have to inject any sort of 'site builder', I could just inject a site itself and I'll get back an already persisted site:

             

            <snip>
            @Inject
            UserAccess userAccess;

            @Inject Site persistedSite;


            @Test

            public void newUser() {

               String serverName = randomAlphanumeric(12);

             

               String email = randomEmail();

               String password = randomAlphanumeric(12);

               User user = new UserBuilder().withEmail(email)

                                                           .withPassword(password)

                                                           .withSite(persistedSite)

                                                           .build();

             

                userAccess.createUser(user);

             

                ....

            </snip>

             

            Are any of these thoughts similar to the approach in your APE backlog?