Skip to content
Gael Lazzari edited this page Sep 10, 2012 · 5 revisions

When testing things, you often have to access objects you don't have access to, because they are hidden implementation details, like private fields, DOM attached widgets, etc.

There are many way to access those kind of objects with gwt-test-utils. This page sums up every techniques you could use and when to use a specific one.

Package protected fields

The most easy way to access a private field in a test is to make this field package protected and write the unit test in the same package as the declaring class. This is a standard Java technique ;-)

How it works

Assuming you have some view with a private button field, just remove the private modifier on this field :

package com.googlecode.gwt.test.sample.client;

public class SampleView extends Composite {

  Button button;
   
   ...
}

Write your unit test in the same package as the SampleViewclass and you will able to access like it was public :

package com.googlecode.gwt.test.sample.client;

@GwtModule("com.googlecode.gwt.test.sample.Sample")
public class SampleViewTest extends GwtTest {

   @Test
   public void clickOnButtonShouldDisplayMessageInLabel() {
      // Arrange
      SampleView view = new SampleView();

      // Act
      Browser.click(view.button);
      
      ...
  }
}

When to use it

As often as possible ! It's the simplest way of accessing a field. But sometimes, you just can't make a field package protected :

  • When the class which declares the field you want an access to is in a third-party dependency.

  • When you're writing integration tests, which test a lot of components (like SampleView) coming from different packages.

  • When for some design purpose, it's really important that this field stays private.

  • When the object you want to access is actually not referenced using a class field. For example, the button could have been instanciated and added to the DOM in SampleView's constructor.

Reflection

Accessing private field is possible using Java Reflection API. Classes from java.lang.reflect are not emulated by GWT's compiler, so they are not usable in a GWTTestCasesubclass.
By chance, you can use it with gwt-test-utils ;-)

How it works

Assuming you have some view with a private button field :

package com.googlecode.gwt.test.sample.client;

public class SampleView extends Composite {

  private Button button;
   
   ...
}

Since the Java Reflection API is not so userfriendly, gwt-test-utils provides some utilities to simplify it in the GwtReflectionUtils class. To access the button, just use :

package com.googlecode.gwt.test.sample.client;

@GwtModule("com.googlecode.gwt.test.sample.Sample")
public class SampleViewTest extends GwtTest {

   @Test
   public void clickOnButtonShouldDisplayMessageInLabel() {
      // Arrange
      SampleView view = new SampleView();
      Button button = GwtReflectionUtils.getPrivateFieldValue(view, "button");

      // Act
      Browser.click(button);
    
      ...
  }
}

As an alternative, you could use the great fest-reflect API, it would work to ;-)

When to use it

Reflection is usefull when you want to access a private field of a class you cannot modify.

But you must be aware accessing private members violates the object encapsulation principle and make your test depending on implementation details that may change over time.

Introspection paths

How it works

TODO

When to use it

TODO

HTML IDs

A natural way for identifying GWT's widgets is to set them an HTML idenfier. It's done this way :

button.getElement().setId("my-button");

But usually, you don't need HTML id on production. That's why GWT comes with a nice UIObject.ensureDebugId() feature to be able to set HTML ids only when debugging.

How it works

TODO

When to use it

TODO