JPA2.0 banned in Poland!

January 7, 2010 6 comments

Yeah really! So I thought it’s time to play a little bit with the brand new JPA2.0 specification. I tried the Hibernate vendor, but since its implementation is still in beta and was throwing more exceptions then I thought a beta should throw, I thought I would give an EclipseLink a try.

Eclipse Link is a former Toplink and now (ever since given back to the community) a reference implementation of JPA standard. Reading this site I learned that to get started with the EclipseLink using Maven, you need to add one dependency:

<dependency>
  <groupId>org.eclipse.persistence</groupId>
  <artifactId>eclipselink</artifactId>
  <version>2.0.0</version>
  <scope>runtime</scope>
</dependency>

But Eclipse Link is still not in the main repo1 repository, so you have to add Eclipse repo information to your pom.xml.

<repository>
   <id>EclipseLink Repo</id>
   <url>http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo</url>
</repository>

And here where the fun begins. If you open repository link (http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo) in your browser  it will redirect you to a nearest mirror near you. Well, for people living in Poland this mirror is http://ftp.man.poznan.pl/eclipse/rt/eclipselink/maven.repo/. The problem is that polish mirror not only lacks the 2.0.0 final implementation, but also you can find eclipse link in 2.0.0-SNAPSHOT version catalogue, but the content of the catalogue will be empty (it has metadata but no jars!). All that is there is just milestonses, nothing else.

So dear readers, EclipseLink JPA2.0 is banned in Poland. It’s official :).

Thanks to the Wicket User Group we can work around this ban, using Belgium mirror repository http://eclipse.a3-system.be/rt/eclipselink/maven.repo. So this should work in your pom.xml:

<repository>
   <id>EclipseLink Repo</id>
   <url>http://eclipse.a3-system.be/rt/eclipselink/maven.repo</url>
</repository>

Funny, isn’t it? 🙂

Categories: News Tags: , ,

A proper way for JPA entities instantiation

January 4, 2010 6 comments

If you read Misko Hevery’s blog you should be pretty much familiar with term testable code (and if you don’t know Misko’s blog then I strongly encourage you to visit his site). Misko divides objects into two main types: service objects and value objects. Each service object provides some set functionalities defined in application logic. Value objects are leafs of the objects’ collaboration graph. They usually encapsulate the data, that is manipulated by services. In other words, in most cases they are the model objects, the nouns that you use to describe the application logic. If you use any ORM technology (like Hibernate or Toplink) value objects will most likely be the entities of your application. And on creating the entities I would like to focus in this post. All examples will be for JPA2.0 entities, since this is standard, but the rules can be easily applied to any other ORM solution. Before we move on to the main topic, which is entities instantiation, lets take a look on how service objects are created.

Most of you probably know that for service instantiation we use dependency injection, which makes code maintainable, testable and more declarative. I suspect that most of you guys know about it, but for all non-believers, I’ve created this very simple example for consideration:

public class UserService implements IUserService {
 @Inject
 private IUserDao dao;

 @Inject
 private IFacebookWS facebook;

 public User logIn(String login, String password) {

   User user = dao.findByLoginAndPassword(login,password);
   if(user == null) {
     return User.GUEST;
   }
   return user;
 }

}

We have those three service classes (and equivalent interfaces): UserDAO for database connection, FacebookWS for communication with facebook webservice and finally UserService that binds the application logic. I use dependency injection so I don’t create any instances of my service classes explicitly. This separation of concerns (separation of usage and instantiation of given class) makes my code more declarative. You, as a other programmer of my team, see that UserService uses UserDAO and FacebookWS, but don’t know how those dependencies are instantiated. And you shouldn’t really care, all that is important is that UserService depends on dao and webservice object.

Thanks to Dependency Injection my tests are now easy to write and easy to read:


@Test
public void shouldReturnGuestUserForIncorrectPassword() {

 // given
 IUserService service = new UserService();

 IUserDAO dao = mock(IUserDAO.class);
 when(dao.findByLogin("someLogin").thenReturn(null));
 inject(service, "dao", dao);

 // when
 User returnedUser = service.logIn("someLogin",
                                   "wrongPassword");

 // then
 assertEquals(User.GUEST, returnedUser);

}

Why (beside the fact that I’m using BDD template given-when-then) tests are easy to read? Important thing is that you (as some other developer of my development team) when looking just at my test, see that to perform logIn action, only IUserDAO dependency is mocked and injected to tested UserService class.

 inject(service, "dao", dao);

This way test is documenting the class its testing. You clearly see that to perform logIn action, facebook web service is not needed. In general to understand how some method works, you can first look at created tests for given class and then (if still needed) check out the implementation. I guarantee that reading tests and implementation is far more comprehensive then just reading implementation.

You might say that to understand how logIn works you wouldn’t need really tests. Remember however that this example is trivial. Imagine class with larger set of dependencies. Self-documenting, easy to read tests, might be really really helpful for maintaining code (especially if the code is one year old and it was developed by someone who is no longer hired in your company).

Secondly, why tests are easy to write? Imagine for example what would happen if I didn’t use DI and I was just instantiating dao and service object in a constructor?


public class UserService implements IUserService {

 private IUserDAO dao;
 private IFacebookWS facebook;

 public UserService() {
   dao = new UserDAO();
   facebook = new FacebookWS();
 }

How I could then mock any of those dependencies? One could say, that I would just simply inject the mock object after constructor. But what if for example when instantiating UserDAO, the dao object is connecting to data base? How would you prevent it from happening in your tests? I believe you couldn’t do it.

Ok, so we use DI for service objects, but what about the value objects? And more importantly what about entities? For the given example, how do we create User objects? The rule of thumb is to just simply use constructors when instantiating value objects. This should not be really a suprise. Value objects are fundamentals of your application, as they mostly just gather domain specific information. They are leafs in the objects relation graph, thus they will most likely be never mocked.

So (following this rule) in our example, User class should looked more or less something like this:

@Entity
public class User {

 @Id
 private String login;
 @Column(nullable = false)
 private String password;
 private String facebookLogin;
 private String facebookPassoword;

 public User(String login,
             String password,
             String facebookLogin,
             String facebookPassword) {
   this.login = login;
   this.password = password;
   this.facebookLogin = facebookLogin;
   this.facebookPassword = facebookPassword;
  }
 }

Everything works fine, even despite the fact in my personal opinion calling new User(“someName”,”somePassowrd”, “someOtherName”, “someOtherPassword”) becomes hardly readable and maintainable. However implementation is still valid. But what shall we do if we get a new requirement for our application:

@Test
public void shouldDefaultFacebookValuesEqualsEquvalentNormalValues() {
 // given
 String login = "a";
 String password = "b";

 // when
 User user = User(login,password);

 // then
 assertEquals(user.getLogin(), user.getFacebookLogin());
 assertEquals(user.getPassowrd(), user.getFacebookPassword());
}

In other words we say that login and password are obligatory in object instantiation, but facebook login and password are not – if not present during initialization, facebook login and password are same as normal login and password.
So what should we do to implement those requirements? Well I hope non of you think to do it like this:

@Entity
public class User {
 @Id
 private String login;
 @Column(nullable = false)
 private String password;
 private String facebookLogin;
 private String facebookPassoword;

 public User(String login,
             String password,
             String facebookLogin,
             String facebookPassword) {
   this.login = login;
   this.password = password;
   this.facebookLogin = facebookLogin;
   this.facebookPassword = facebookPassword;
  }

 public User(String login,
             String password) {
   this.login = login;
   this.password = password;
   this.facebookLogin = login;
   this.facebookPassword = password;
  }
}

You can clearly see the code duplication. Maintaining this code would turn into a nightmare in no time. A rather well-known solution is to implement something that some programmers call “telescoping constructor pattern” (name I first encountered in Joshua Bloch “Effective Java”) . For our scenario this patter would look like this:

@Entity
public class User {
 @Id
 private String login;
 @Column(nullable = false)
 private String password;
 private String facebookLogin;
 private String facebookPassoword;

 public User(String login,
             String password) {
   this(login, password, login);
 }
 public User(String login,
             String password,
             String facebookLogin) {
   this(login, password, facebookLogin, password);
 }
 public User(String login,
            String password,
            String facebookLogin,
            String facebookPassword) {
   this.login = login;
   this.password = password;
   this.facebookLogin = facebookLogin;
   this.facebookPassword = facebookPassword;
 }
}

You define constructor with minimal set of parameters (meaning parameters obligatory to object initialization). Then you continue on extending other constructors with parameters until you reach the constructor that defines them all. This works fine for small set of parameters, but can quickly turn into horror when number of parameters grows and so the vast number of possible constructors.

Another solution would be to go with the JavaBeans pattern.

@Entity
public class User {
 @Id
 private String login;
 @Column(nullable = false)
 private String password;
 private String facebookLogin;
 private String facebookPassoword;

 public User() {
 }

 public void setLogin(String login) {
   this.login = login;
 }

 public void setPassword(String password) {
   this.password = password;
 }

 public void setFacebookLogin(String facebookLogin) {
   this.facebookLogin = facebookLogin;
 }

 public void setFacebookPassword(String facebookPassword) {
   this.facebookPassword = facebookPassword;
 }
}

You create object without any parameters and use set methods to define appropriate values. Solution works fine with any number of parameters and is wildly use by many developers. In fact I’ve seen it almost in every second project I ever worked on. Since every single IDE gives automatic setter and getter generation, most developers follow this simple pattern:

1. create entity class in they favourite IDE (e.g User )
2. define all needed attributes as private fields (e.g login, password, facebookLogin, facebookPassword)
3. auto-generate getters and setters

This pattern is quick when creating entity classes, but it has its flaws. The fact that it generates a lot of code that you might never really need (from time to time check your code on how many getters you have that are never really use, you might get surprised), already makes it a no-no. But it has one more and a lot bigger disadvantage: it allows you to create entity object, that does not have all the obligatory fields set. Example:

User user = new User();
user.setLogin("john");
user.setFacebookLogin("jhawk");
user.setFacebookPassword("12345");

userDao.persist(user);
}

Assuming that userDao.persist(User) calls EntitManager’s persist method, running the code above will throw an exception by the JPA provider, since not-nullable password field was never set.

Ok, so what can we do about it? Joshua Blooch gives fine example of builder pattern.

Instead of making the desired object directly, the client calls a constructor (or static factory) with all of the required parameters and gets a builder object. Then the client calls setter-like methods on the builder object to set each optional parameter of interest. Finally, the client calls a parameterless build method to generate the object, which is immutable. The builder is a static member class of the class it builds.

This works fine for value objects that are immutable (meaning once set, their state is never changed). Consider the example below:

public class Coffee {
 private final CoffeType type;
 private final int cupSize;
 private final boolean hasMilk;

 public static class Builder {
   public CoffeeType type;
   public int cupSize;
   public boolean hasMilk;

   public Builder(CoffeeType type, int cupSize) {
      this.type = type;
      this.cupSize = cupSize;
      hasMilk = false;
   }

   public Builder withMilk() {
      hasMilk = true;
      return this;
   }

   public Coffee build() {
     return new Coffee(this);
   }
 }

 private Coffee(Builder builder) {
   this.type = builder.type;
   this.cupSize = builder.cupSize;
   this.hasMilk = builder.hasMilk;
 }
}

Reading the code above you can clearly see that coffee type and cup size are obligatory and whether coffee should or shouldn’t have milk is not mandatory field. Creating Coffee could look more or less like this:

Coffee coffee = new Coffee.Builder(CoffeeType.Expresso, 3).withMilk().build();
}

Of course using this pattern for value object that has two parameters would be an exaggeration. J. Blooch says:

In summary, the Builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters, especially if most of those parameters are optional.

The problem is that entities are not immutable by nature. So the question still remains, how can we construct entity classes? What I really like to do is combine JavaBeans pattern and Builder pattern when creating entities. For all entity attributes I create private fields, those that are obligatory become parameters for the public constructor. Since JPA requires that each entity has a parameter-less constructor, I create one, but I give him protected access level, so in most cases it won’t be accessible from client code. I create setter methods for all fields that require them at the moment and incrementally add them whenever needed. So our User example would look more or less like this:

@Entity
public class User {
 @Id
 private String login;
 @Column(nullable = false)
 private String password;
 private String facebookLogin;
 private String facebookPassoword;

 protected User() { }

 public User(String login, String password) {
   this.login = login;
   this.password = password;
 }

 public void setFacebookLogin(String facebookLogin) {
   this.facebookLogin = facebookLogin;
 }

 public void setFacebookPassword(String facebookPassword) {
   this.facebookPassword = facebookPassword;
 }
}

And if I would like to stick with all previously mentioned in this posts requirements, we could slightly enhance the constructor to look like this:

 public User(String login, String password) {
   this.login = login;
   this.password = password;
   this.facebookLogin = login;
   this.facebookPassword = password;
 }

Now instantiating User class requires two parameters (login and password). You gain flexibility of JavaBeans, with security of the Builder pattern. Of course this is only hybrid of this two solutions, so it is still possible to create malformed entity (instantiated with obligatory values and then set them again to nulls with setter methods), but this is less likely to happen. You gain on readability, since quick look on constructor parameters gives you notion of all obligatory attributes.

You can also combine this solution with JSR-303 validation and unit testes, solution that can shield you from creating malformed entities… But this is probably topic for another post.

But I wonder how you create your entity classes. Do you know any other ways to create entity classes so their instantiation is safe, readable and maintainable?

Categories: Articles Tags: , ,

Java Killers #002 – Add me, check me

December 31, 2009 2 comments
Categories: Java Killers Tags:

Testing EJB3.0 Presentation at Parleys

December 17, 2009 Leave a comment

Szczecin JUG added to Parlays my presentation about Testing EJB3.0 (though the presentation should really be named: Testing and testing EJB3.0), that I was doing last year at Java4People conference in Szczecin, Poland.

Presentation is in polish language though, so don’t be surprised :). Presentation can be reached here.

Categories: Presentations

I wasn’t here for quite a while…

December 14, 2009 5 comments

I wasn’t here for quite a while… For the last three months I was quite busy since my life has changed rapidly. To tell the long story short:

1. First this thing happend:

2. Then we went there:

3. And then I’ve learned the consequences 🙂

Meanwhile I changed my job, did one commercial project using WicketCool (I will write about it soon) and I can finally get back to my blog ;). Hope to see you all soon.

Categories: News

Writing EVEN MORE readable and maintainable tests

August 25, 2009 2 comments

If you follow my blog you know that few weeks ago I posted an article about writing readable and maintainable tests. My understanding of readable and maintainable tests evolves in time, my views and opinions change and  thus my posts need update.

I thought that the easiest way to show you the changes will be an example. As before, examples are shown for Wicket application, however the rules can be applied to any other frontend frameworks (JSF applications can use for instance JSFUnit project). Secondly, if you haven’t read my article about readable and maintainable tests, I encourage you to do so, since this post is simply update of the previous one. Furthermore post about WicketTestBase should be helpful as well, since all examples inherit from WicketTestBase class.

But lets move on to our example. Imagine we are told to implement user story “Add new Applicant”.  General steps are as follows:

  1. User enters welcome page
  2. User clicks link called ‘create new applicant’
  3. User is given a form that he fills with Applicant data (name, surname and age)
  4. Users is presented with Applicants list, where newly added Applicant is visible
  5. Applicant is added to the Application he is applying to

Before I explain you all the  necessary details, please let me show you how would the final tests for this scenario look like. I want you to see them now, just to let you know how readable tests can really be. For the purpose of this  example I will only show two tests, however it should be obvious that in real life overall number of tests can be much bigger. The tests look as follow:

test #1  – Should show ApplicantsList after adding applicant

public void shouldShowApplicantsListAfterAddingApplicant
                  throws Exception {
 // given
 user.enters().welcomePage();
 user.clicks().createNewApplicationLink();

 // when
 user.fills().addApplicantForm("Adam", "Bauer", 27);
 user.clicks().saveAndExitButton();

 // then
 onpage.applicantsList.exists().isVisible().and().isOfType(ListView.class);
}

test #2 – Should show added applicant informations

public void shouldShowAddedApplicantInformations
                  throws Exception {
 // given
 user.enters().welcomePage();
 user.clicks().createNewApplicationLink();

 // when
 user.fills().addApplicantForm("Adam", "Bauer", 27);
 user.clicks().saveAndExitButton();

 // then
 onpage.applicantsList
            .containsElements(application.getApplicants());
 onpage.applicantsList
            .element(0, "appliocantName").isLabelWithValue("Adam");
 onpage.applicantsList
            .element(0, "appliocantSurname").isLabelWithValue("Bauer");
 onpage.applicantsList
            .element(0, "appliocantAge").isLabelWithValue("27");
}

Readable isn’t it? The tests themselves can be read as a normal sentences. They should give you this feeling that you are reading a book. This is what self-documenting code is all about. When you read the test, it is quite clear what the implementation should do. Test are understandable, test base is comprehensive. And you know what? It will still be, even after one year. Or maybe you are soon planning to hire new developer? Not a problem at all, he will easily understand them as well. That is what all the readability is all about!
Notice that in fact when reading those tests you are not even aware of the fact that they are testing Wicket application. Remember that tests should always represent the requirements! If those test fail and fixing them is not a matter of change in one or two lines of code, then it only means the requirements changed. However if the button gets different name or ApplicantsList suddenly gets different path, then fixing those tests is simply change in one line of code. This is what all the maintainability is all about!

The question remains then, what changes were applied. If you were asked to write similar tests and you would follow my previous guidelines, you would probably end up with something like this:

test #1 – Should show ApplicantsList after adding applicant

public void shouldShowApplicantsListAfterAddingApplicant
                  throws Exception {
 // given
 enterer.entersWelcomePage();
 clicker.clickCreateNewApplicationLink();

 // when
 formFiller.fillsAddApplicantForm("Adam", "Bauer", 27);
 clicker.clicksSaveAndExitButton();

 // then
 String pathToApplicantsList = "path:to:applicantslist";
 tester.getComponentFromLastRenderedPage(pathToApplicantsList);
 tester.assertVisible(pathToApplicantsList);
 tester.assertComponent(pathToApplicantsList, ListView.class);
}

test #2 – Should show added applicant informations

public void shouldShowAddedApplicantInformations
                  throws Exception {
 // given
 enterer.entersWelcomePage();
 clicker.clickCreateNewApplicationLink();

 // when
 formFiller.fillsAddApplicantForm("Adam", "Bauer", 27);
 clicker.clicksSaveAndExitButton();

 // then
 String pathToApplicantsList = "path:to:applicantslist";
 tester.assertListView(pathToApplicantsList, application.getApplicants());
 tester.assertLabel(pathToApplicantsList + "applicantName", "Adam");
 tester.assertLabel(pathToApplicantsList + "applicantSurname", "Bauer");
 tester.assertLabel(pathToApplicantsList + "applicantAge", "27");
}

It’s good already, but it has its flaws. First lets look at helper classes, they great at aggregating common actions (entering pages, clicking and form filling), but when we read the test

 (...)
 // given
 enterer.entersWelcomePage();
 clicker.clickCreateNewApplicationLink();

 // when
 formFiller.fillsAddApplicantForm("Adam", "Bauer", 27);
 clicker.clicksSaveAndExitButton();
(...)

it doesn’t sound right. Try to read above code out loud. If you do that, you will quickly learn that there is something missing. Lets try it, read this out loud:

“Enterer enters welcome page”
“Clicker clicks create new application link”
“FormFiller fills add applicant form”

What is wrong with it? Why doesn’t it sound right? Well we basically miss person who is responsible for all the clicking, entering and form filling. We miss here the User! Whenever I read test, I want to hear sentences like this:

User enters welcome page”
User clicks create new application link”
User fills add applicant form”

I mean who is this enterer, what is this clicker, were did this formFiller came from? It is User who does the whole work. Clicker, Enterer and FormFiller are just representations of the actions he does. Taking that fact into consideration I created another helper class called Userer.

public class Userer {

  private Clicker clicker;
  private Enterer enterer;
  private FormFiller formFiller;

  public Userer(Clicker clicker,
                Enterer enterer,
                FormFiller formFiller) {
      this.clicker = clicker;
      this.enterer = enterer;
      this.formFiller = formFiller;
  }

  public Clicker clicks() {
      return clicker;
  }

  public FormFiller fills() {
      return formFiller;
  }

  public Enterer enters() {
      return enterer;
  }
}

This class simply aggregates Clicker, FormFiller and Enterer. Userer becomes field in WicketTestBase (base class for all my Wicket tests) as shown below:

public class WicketTestBase {

    (...)
    protected Clicker clicker;
    protected Enterer enterer;
    protected FormFiller formFiller;

    protected Userer user;
    (...)

    private void initHelpers() {
        clicker = new Clicker(tester, enhancedTester);
        formFiller = new FormFiller(tester, enhancedTester);
        enterer = new Enterer(tester, enhancedTester, clicker, formFiller);
        user = new Userer(clicker, enterer, formFiller);
    }
    (...)

From now on you can use this ‘user’ field in your tests. Now we can refactor our test:

  1. calls to clicker become calls to user.clicks() e.g clicker.clicksSaveLink becomes user.clicks().saveLink() (notice we also changed clickSaveLink method name to saveLink)
  2. calls to formFiller become calls to user.fills() e.g formFiller.fillsAddApplicantForm(“Adam”, “Bauer”, 27) becomes user.fills().addApplicantForm(“Adam”, “Bauer”, 27)
  3. calls to enterer become calls to user.eneters() e.g enterer.entersWelcomePage() becomes users.enters.welcomePage()

Now our previous test will look like this:

test #1 – Should show ApplicantsList after adding applicant

public void shouldShowApplicantsListAfterAddingApplicant
                  throws Exception {
 // given
 user.enters().welcomePage();
 user.clicks().createNewApplicationLink();

 // when
 user.fills().addApplicantForm("Adam", "Bauer", 27);
 user.clicks().saveAndExitButton();

 // then
 String pathToApplicantsList = "path:to:applicantslist";
 tester.getComponentFromLastRenderedPage(pathToApplicantsList);
 tester.assertVisible(pathToApplicantsList);
 tester.assertComponent(pathToApplicantsList, ListView.class);
}

test #2 – Should show added applicant informations

public void shouldShowAddedApplicantInformations
                  throws Exception {
 // given
 user.enters().welcomePage();
 user.clicks().createNewApplicationLink();

 // when
 user.fills().addApplicantForm("Adam", "Bauer", 27);
 user.clicks().saveAndExitButton();

 // then
 String pathToApplicantsList = "path:to:applicantslist";
 tester.assertListView(pathToApplicantsList, application.getApplicants());
 tester.assertLabel(pathToApplicantsList + "applicantName", "Adam");
 tester.assertLabel(pathToApplicantsList + "applicantSurname", "Bauer");
 tester.assertLabel(pathToApplicantsList + "applicantAge", "27");
}

Pretty readable right? All looks good, but imagine what will happen, when path to ApplicationList change or it will become PropertyListView (instead of ListView)? Some time ago I realized that every action of the test scenarios falls into one of four categories. User either enters application, clicks a link or button, fills form with data or assert state of the application. For entering, filling and clicking I created helper classes that encapsulate those actions (Enterer, FormFiller and Clicker), however assertion still did not get its representation. Thus I created another helper class called Weberer.

public class Weber {

    // components
    public PageElement applicantsList;

    // testers
    private WicketTester tester;
    private EnhancedWicketTester enhancedWicketTester;

    public Weber(WicketTester tester,
                         EnhancedWicketTester enhancedWicketTester) {
        this.tester = tester;
        this.enhancedWicketTester = enhancedWicketTester;

        createPageElements(tester, enhancedWicketTester);
    }

    private void createPageElements(WicketTester tester,
                                    EnhancedWicketTester enhancedWicketTester) {
        applicantsList = new PageElement("applicationForm:panel:listApplicantsPanel:applicants",
                                         tester, enhancedWicketTester);
    }
}

This class represents informations presented on page and helps to perform various assertion actions on those objects. Weberer holds reference to public fields of type PageElement.

public class PageElement implements IPageElement {

    private final WicketTester tester;
    private final EnhancedWicketTester enhancedWicketTester;
    private final String path;

    public PageElement(String path, WicketTester tester, EnhancedWicketTester enhancedWicketTester) {
        this.tester = tester;
        this.enhancedWicketTester = enhancedWicketTester;
        this.path = path;
    }
    public PageElement exists() {
        tester.getComponentFromLastRenderedPage(path);
        return this;
    }

    public PageElement isVisible() {
        tester.assertVisible(path);
        return this;
    }

    (....)

Those fields represent different elements that can be found on page. So for example if suddenly you need to make some assertions on login form, then you will add to Weberer object new field:

public class Weber {

    // components
    public PageElement loginForm;
    (...)

    private void createPageElements(WicketTester tester,
                                                         EnhancedWicketTester enhancedWicketTester) {
        loginForm = new PageElement("path:to:login:form",
                                                            tester, enhancedWicketTester);
        (...)
    }

Since Weberer is also a filed in WicketTestBase class:

public class WicketTestBase {

    (...)
    protected Userer user;
    protected Weber onpage;
    (...)

you can access your newly created element directly from your tests:

   onpage.loginForm.exists();
   onpage.loginForm.isVisible();

When we apply those rules into our test, they will final look like this:

test #1 – Should show ApplicantsList after adding applicant

public void shouldShowApplicantsListAfterAddingApplicant
                  throws Exception {
 // given
 user.enters().welcomePage();
 user.clicks().createNewApplicationLink();

 // when
 user.fills().addApplicantForm("Adam", "Bauer", 27);
 user.clicks().saveAndExitButton();

 // then
 onpage.applicantsList.exists().isVisible().and().isOfType(ListView.class);
}

test #2 – Should show added applicant informations

public void shouldShowAddedApplicantInformations
                  throws Exception {
 // given
 user.enters().welcomePage();
 user.clicks().createNewApplicationLink();

 // when
 user.fills().addApplicantForm("Adam", "Bauer", 27);
 user.clicks().saveAndExitButton();

 // then
 onpage.applicantsList
            .containsElements(application.getApplicants());
 onpage.applicantsList
            .element(0, "appliocantName").isLabelWithValue("Adam");
 onpage.applicantsList
            .element(0, "appliocantSurname").isLabelWithValue("Bauer");
 onpage.applicantsList
            .element(0, "appliocantAge").isLabelWithValue("27");
}

The test code is now easy to read and easy to maintain. All the Wicket specific code is hidden behind those helper classes. This not only helps to maintain test in a short time (when for example path to some components change) but also in a long run (when for example API of the WicketTester change in the 1.5 version). It will be lot easier to apply those changes only to 5 helper classes, then to base of few hundred tests already implemented in your application.

All code presented here will be soon (in a matter of days) added to WicketCool project, so you will be able to see WicketTestBase in action.

WicketTestBase – base class for testing Wicket + Spring web applications

August 17, 2009 5 comments

When writing integration tests in Wicket, there are few initialization steps that need to be executed before actual testing:

  1. data initialization – tests often need static data in the database for each and every test method.
  2. tester initialization – tester is initialized with Application and Session object, given locale needs to be set, Spring injector needs to be pre-configured etc.
  3. helper class initialization

Putting those actions to some init method (annotated with @Before in JUnit) would be a good idea. However I thought that since those steps are done in every single test, smart thing to do is moving them up in class hierarchy into some super class.
This is how WicketTestBase was created. Base class for integration tests in Wicket + Spring applications. Let’s take a look at it:

public class WicketTestBase {

 @Autowired
 private ApplicationContext applicationContext;

 protected WicketTester tester;
 protected EnhancedWicketTester enhancedTester;
 protected Clicker clicker;
 protected Enterer enterer;
 protected FormFiller formFiller;
 (...)

WicketTestBase has six protected fields. Spring’s ApplicationContext is injected, other five fields (tester, enhanced tester and helper classes) need to be initialized for every test. All fields have protected access level,  thus they can be reached from test classes that will extend WicketTestBase.

If you haven’t heard about enhanced tester, then please follow this article. If Clicker, FormFiller and Enterer are new to you, then kindly check my article about readable tests.

public void init() {
 populateData();
 createTester();
 initHelpers();
}

Next we have the public init method. This method will be called with every test. Method populateData is empty by default, but can be extended in test classes inheriting from WicketTestBase.

 /**
  * Override to populate data in database
  * for each test
  */
 protected void populateData() {
     // override in test if necessary
 }

Method createTester is the most complex one, but still it should be clear what it does.

private void createTester() {
 tester = new WicketTester((WebApplication)
 applicationContext.getBean("wicketApplication"));
 tester.setupRequestAndResponse();
 tester.getWicketSession().setLocale(getLocale());
 tester.getApplication().addComponentInstantiationListener(
 new SpringComponentInjector(tester.getApplication(),
 applicationContext));
 enhancedTester = new EnhancedWicketTester(tester);
 initSessionBeforeTest((UserSession) tester.getWicketSession());
}

First WicketTester object is created with Wicket Application object as constructor’s parameter. Note that Wicket Application object is taken from Spring’s ApplicationContext. Then Spring pre-configuration takes place and at the end Enhanced WicketTester is created.

Note also that two hook methods are called: getLocale and initSessionBeforeTest.

/**
 * Override to change locale
 * @return locale, default EN
 */
 protected Locale getLocale() {
 return new Locale("EN");
 }

Method getLocale returns default local for the tests. By default it returns EN, but extending classes can override this method to provide different locale.

 /**
 * Insert application specific properties to session
 * @param session
 */
 protected void initSessionBeforeTest(UserSession session) {
 // override in test if necessary
 }

Method initSessionBeforeTest is empty by default. It should be overridden if you would like to insert any test specific data into session before each test.

At the end helper classes are initialized.

private void initHelpers() {
 clicker = new Clicker(tester, enhancedTester);
 formFiller = new FormFiller(tester, enhancedTester);
 enterer = new Enterer(tester, enhancedTester, clicker, formFiller);
}

And that is it. Below WicketTestBase in its full glory:

public class WicketTestBase {

 @Autowired
 private ApplicationContext applicationContext;

 protected WicketTester tester;
 protected EnhancedWicketTester enhancedTester;
 protected Clicker clicker;
 protected Enterer enterer;
 protected FormFiller formFiller;

 public void init() {
     populateData();
     createTester();
     initHelpers();
 }

 private void createTester() {
     tester = new WicketTester((WebApplication)
                        applicationContext.getBean("wicketApplication"));
     tester.setupRequestAndResponse();
     tester.getWicketSession().setLocale(getLocale());
     tester.getApplication().addComponentInstantiationListener(
                      new SpringComponentInjector(tester.getApplication(),
                      applicationContext));
     enhancedTester = new EnhancedWicketTester(tester);
      initSessionBeforeTest((UserSession) tester.getWicketSession());
 }

 private void initHelpers() {
    clicker = new Clicker(tester, enhancedTester);
    formFiller = new FormFiller(tester, enhancedTester);
    enterer = new Enterer(tester, enhancedTester, clicker, formFiller);
 }

 /**
  * Override to change locale
  * @return locale, default EN
  */
 protected Locale getLocale() {
     return new Locale("EN");
 }

 /**
  * Insert application specific properties to session
  * @param session
  */
  protected void initSessionBeforeTest(UserSession session) {
     // override in test if necessary
  }

 /**
  * Override to populate data in database
  * for each test
  */
 protected void populateData() {
     // override in test if necessary
 }
}

Simplest example of test extending from WicketTestBase will look like this:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:testApplicationContext.xml"})
@Transactional
public class NameOfTheTest extends WicketTestBase {

    @Before
    public void init() {
        super.init();
    }

}

ContextConfiguration points to Spring’s configuration xml file (in this case testApplicationContext.xml) and Transactional annotation simply makes all test methods transactional. Worth mentioning is the fact that all this transactions are rolled back after each test method finish it’s execution, thus you won’t have to implement any destroyData method – this is automatically done for you.

Usage of WicketTestBase can be also found in WicketCool project. If interested, check it out.

see also:

  1. Writing readable and maintable integration tests (not only) in Wicket
  2. Test template you should always use
Categories: Wicket Tags: ,