Clone wiki

Java EE 6-Galleria / BeanVerification

JavaBean Verification

The behavior associated with the getters and setters in the properties of JavaBeans are fairly easy to verify. All one needs to do, is to invoke the setter first, then the getter, and verify whether the instance returned by the getter is equal to the instance passed to the setter. The project uses the BeanVerifier class (under the src/tests/java root of the galleria-ejb module) to this extent; this may be extracted into a separate project due to it's universal utility.

The BeanVerifier

The BeanVerifier expose the following API:

  • static <T> BeanVerifier<T> forProperty(Class<T> type, PropertyDescriptor descriptor, ITypeFactory typeFactory)
  • void verify()

The forProperty method allows you to create a BeanVerifier for a given class, with the supplied JavaBean PropertyDescriptor, and a type factory. The created BeanVerifier can then be used to validate the correctness of the property associated with the PropertyDescriptor. The provided type factory would be used to create instances of types, to use in the property verification process.

The verify method is then used to assert whether the JavaBean property satisfies our pre-requisite.

Using the BeanVerifier

In a slight deviation from it's name, the BeanVerifier verifies the correctness of the property associated with a PropertyDescriptor. One needs to create multiple such BeanVerifiers for verifying all the properties of a JavaBean. This is easily done by using the Parameterized testrunner of JUnit 4, to obtain all the PropertyDescriptors.

This approach also allows you to not use the BeanVerifier intentionally, if a certain property should not be verified by the BeanVerifier. A separate test may exist to verify the behavior of such a property.

To examine the usage of the BeanVerifier closely, we shall see how the AlbumBeanVerifier test operates:

The test class is annotated with the JUnit 4 @RunWith annotation - the Parameterized testrunner specified as the testrunner for this test class.

@RunWith(Parameterized.class)
public class AlbumBeanVerifier

The parameters for each test run as created using the properties() method.

    @Parameters
    public static Collection<Object[]> properties()
    {
        return VerifierHelper.getProperties(TEST_TYPE);
    }

Each instance of an AlbumBeanVerifier is created using the one-parameter constructor, that will be used by the test runner. The parameter for the constructor itself will be obtained from the Collection returned by the @Parameters annotated method. Quite obviously, the @Parameters method should return a Collection of Object arrays, with each array containing only one PropertyDescriptor. The VerifierHelper class will aid in the creation of such Collections.

    private PropertyDescriptor descriptor;
    ...
    public AlbumBeanVerifier(PropertyDescriptor descriptor)
    {
        this.descriptor = descriptor;
    }

The @Test method is quote simple. All it does is create a BeanVerifier instance for the PropetyDescriptor associated with the current test class instance. It then uses the BeanVerifier to verify the correctness of the property getters and setters.

There is of course, logic to override the test for the coverPhoto property of an Album. Vetoing of the test for the coverPhoto property could also have been done by removing the associated PropertyDescriptor from the Collection returned by the @Parameters method.

    @Test
    public void testProperty() throws Exception
    {
        if (descriptor.getName().equals("coverPhoto"))
        {
            // CoverPhoto property verification cannot be done using ths
            // BeanVerifier, as the setter checks for valid photos within the
            // photos property. Hence, the test is treated as a pass.
            // Verification is done separately in the AlbumOtherTests class.
            return;
        }
        logger.info("Verifying property {} in bean {}", descriptor.getName(), TEST_TYPE);
        BeanVerifier<Album> verifier = BeanVerifier.forProperty(TEST_TYPE, descriptor, typeFactory);
        verifier.verify();
    }

Updated