Alternate method of BeanInfo creation? - java

I recently moved my spring application from java 1.6 to java 1.8. This has caused the spring bootstrapping to take an order of magnitude longer (20s before, 4mins now). Tracing the cause has led me to the CachedIntrospectionResults class, which is created for every bean. When created it calls,
beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?
Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
Introspector.getBeanInfo(beanClass));
Introspector then creates the bean info, in java 1.6, it calls
private BeanDescriptor getTargetBeanDescriptor() {
// Use explicit info, if available,
if (explicitBeanInfo != null) {
BeanDescriptor bd = explicitBeanInfo.getBeanDescriptor();
if (bd != null) {
return (bd);
}
}
// OK, fabricate a default BeanDescriptor.
return new BeanDescriptor(this.beanClass);
}
However in java 1.8 it now calls,
private BeanDescriptor getTargetBeanDescriptor() {
// Use explicit info, if available,
if (explicitBeanInfo != null) {
BeanDescriptor bd = explicitBeanInfo.getBeanDescriptor();
if (bd != null) {
return (bd);
}
}
// OK, fabricate a default BeanDescriptor.
return new BeanDescriptor(this.beanClass, findCustomizerClass(this.beanClass));
}
private static Class<?> findCustomizerClass(Class<?> type) {
String name = type.getName() + "Customizer";
try {
type = ClassFinder.findClass(name, type.getClassLoader());
// Each customizer should inherit java.awt.Component and implement java.beans.Customizer
// according to the section 9.3 of JavaBeans™ specification
if (Component.class.isAssignableFrom(type) && Customizer.class.isAssignableFrom(type)) {
return type;
}
}
catch (Exception exception) {
// ignore any exceptions
}
return null;
}
This method as far as I can see was added with java 1.7, and since I don't define any customizer classes, it searches my full classpath then throws an exception which ends up taking a few hundred ms. The result being that each bean takes ~500ms to init. A huge hit to startup time.
I am now trying to find a way to work around this problem,
The spring documentation says to implement a BeanInfoFactory in order to customize the beanInfo creation. But I can't find anywhere that says how to actaually create BeanInfo for a provided class.
How would I actually do that? Introspector uses a bunch of private constructors to build it up so I can't really follow it, and simply returning an empty BeanInfo blows spring up. What does spring actually want with the beaninfo?
Any ideas?

Normally, when you provide an explicit BeanInfo, the Introspector will gather information automatically whenever the explicit BeanInfo returns null. So there should be no problem providing an empty BeanInfo that only returns a non-null BeanDescriptor to prohibit the automatic Customizer search.
For example:
import java.beans.*;
import java.util.stream.Stream;
public class BeanInfoTest {
public static void main(String... arg) throws IntrospectionException {
BeanInfo bi=Introspector.getBeanInfo(TheComponent.class, Object.class);
System.out.println("properties: ");
Stream.of(bi.getPropertyDescriptors())
.map(p->p.getPropertyType().getSimpleName()+' '+p.getName())
.forEach(System.out::println);
}
public static class TheComponent {
String foo;
int bar;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public int getBar() {
return bar;
}
public void setBar(int bar) {
this.bar = bar;
}
}
public static class TheComponentBeanInfo extends SimpleBeanInfo {
/** Overridden to prevent the automated search for a Customizer */
#Override
public BeanDescriptor getBeanDescriptor() {
System.out.println("Providing my explicit BeanDescriptor");
return new BeanDescriptor(TheComponent.class);
}
}
}
will print
Providing my explicit BeanDescriptor
properties:
int bar
String foo
So it found the properties using automated search while using the explicit BeanDescriptor.

Related

Checking an object is correctly built in Java

This is a general issue/problem that I have come across. I wondered if anyone knows of any well suited design patterns or techniques.
private ExternalObject personObject;
private String name;
private int age;
private String address;
private String postCode;
public MyBuilderClass(ExternalObject obj)
this.personObject=obj;
build();
}
public build() {
setName(personObject.getName());
setAge(personObject.getAge());
setAddress(personObject.getAddress());
setPostCode(personObject.getPostCode());
.
.
. many more setters
}
The class above takes external objects from a queue and constructs MyBuilderClass objects.
A MyBuilderClass object is successfully built if all of the fields have been set to non-null non-empty values.
There will be many MyBuilderClass objects that cannot be built because data will be missing from the ExternalObject.
My problem, what is the best way to detect if an object has been correctly built?
I could check for null or empty values in the set methods and throw an exception. The problem with this approach is throwing exceptions is expensive and it will clogg the log files up because there will be many instances where an object cannot be built;
What other approaches could I use?
Correct me if I'm wrong: you are trying to find a good way to check if an object is valid, and if it is not, tell the client code about this without using an exception.
You can try a factory method:
private MyBuilderClass(ExternalObject obj)
this.personObject=obj;
build();
}
public static MyBuilderClass initWithExternalObject(ExternalObject obj) {
// check obj's properties...
if (obj.getSomeProperty() == null && ...) {
// invalid external object, so return null
return null;
} else {
// valid
MyBuilderClass builder = new MyBuilderClass(obj);
return builder.build();
}
}
Now you know whether an object is valid without using an exception. You just need to check whether the value returned by initWithExternalObject is null.
I wouldn't throw exceptions in cases that aren't exceptional. And as the only way for a constructor not to produce an object is to throw, you should not delay validation to the constructor.
I'd still recommend the constructor to throw if its results were to be invalid, but there should be a validation before that, so you don't even call the constructor with an invalid ExternalObject.
It's up to you if you want to implement that as a static method boolean MyBuilderClass.validate(ExternalObject) or by using the builder pattern with this validation.
Another approach for such a validation is to use java Annotations:
Make a simple annotaion class, let's say Validate:
#Target({ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
#interface Validate {
boolean required() default true;
}
then annotate the fields you want to be present as #Validate(required=true):
class MyBuilderClass {
private ExternalObject externalObject;
#Validate(required=true)
private String name;
#Validate(required=false) /*since it's a primitive field*/
private int age;
#Validate(required=true)
private String address;
#Validate(required=true)
private String postCode;
MyBuilderClass(ExternalObject externalObject) {
this.externalObject = externalObject;
build();
}
public void build() {
setName(personObject.getName());
setAge(personObject.getAge());
setAddress(personObject.getAddress());
setPostCode(personObject.getPostCode());
}
//.
//.
//. many more setters
}
And then add this method in the MyBuilderClass class, in order to check if your Object is built correctly:
public boolean isCorrectlyBuilt() throws IllegalAccessException {
boolean retVal = true;
for (Field f : getClass().getDeclaredFields()) {
f.setAccessible(true);
boolean isToBeChecked = f.isAnnotationPresent(Validate.class);
if (isToBeChecked) {
Validate validate = f.getAnnotation(Validate.class);
if (validate.required()/*==true*/) {
if (f.get(this) == null) {
retVal = false;
break;
/* return false; */
}
}
}
}
return retVal;
}
Here is an example of use :
public static void main(String[] args) throws Exception {
ExternalObject personObject = new ExternalObject();
personObject.setAge(20);
personObject.setName("Musta");
personObject.setAddress("Home");
personObject.setPostCode("123445678");
MyBuilderClass myBuilderClass = new MyBuilderClass(personObject);
System.out.println(myBuilderClass.isCorrectlyBuilt());
}
Output : true because the object is correctly built.
This will allow you to choose the fields that you want to be in the structure by reflection, without bringing those inherited from a base class.
As this previous answer suggests, here are 2 options either of which should be added after you have tried to set the variables.
use reflection to check whether any of the variables are null. (As mentioned in comments this will check all fields in this object but be careful with fields in any superclasses).
public boolean checkNull() throws IllegalAccessException {
for (Field f : getClass().getDeclaredFields())
if (f.get(this) != null)
return false;
return true;
}
perform a null check on each variable.
boolean isValidObject = !Stream.of(name, age, ...).anyMatch(Objects::isNull);
Previous answer
From what I've come across you could overwrite the equals method of your object and compare it with a valid example object. Its dirty and might only work in some cases.
Your approach is the best I could think of. Write a seperate method or class that has for example a static validate method. You could reuse it anywhere.

How to iterate over all the declared fields of an object of a class [duplicate]

I need to make sure that no object attribute is null and add default value in case if it is null. Is there any easy way to do this, or do I have to do it manually by checking every attribute by its getters and setters?
You can use reflection to iterate over the object's field, and set them. You'd obviously need some sort of mapping between types or even field names and required default values but this can be done quite easily in a loop. For example:
for (Field f : obj.getClass().getFields()) {
f.setAccessible(true);
if (f.get(obj) == null) {
f.set(obj, getDefaultValueForType(f.getType()));
}
}
[Update]
With modern Java, you can use annotations to set the default values for fields on a per class basis. A complete implementation might look like this:
// DefaultString.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public #interface DefaultString {
String value();
}
// DefaultInteger.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention(RetentionPolicy.RUNTIME)
public #interface DefaultInteger {
int value();
}
// DefaultPojo.java:
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class DefaultPojo {
public void setDefaults() {
for (Field f : getClass().getFields()) {
f.setAccessible(true);
try {
if (f.get(this) == null) {
f.set(this, getDefaultValueFromAnnotation(f.getAnnotations()));
}
} catch (IllegalAccessException e) { // shouldn't happen because I used setAccessible
}
}
}
private Object getDefaultValueFromAnnotation(Annotation[] annotations) {
for (Annotation a : annotations) {
if (a instanceof DefaultString)
return ((DefaultString)a).value();
if (a instanceof DefaultInteger)
return ((DefaultInteger)a).value();
}
return null;
}
}
// Test Pojo
public class TestPojo extends DefaultPojo {
#DefaultString("Hello world!")
public String stringValue;
#DefaultInteger(42);
public int integerValue;
}
Then default values for a TestPojo can be set just by running test.setDetaults()
You need to manually filter input to constructors and setters. Well... you could use reflection but I wouldn't advise it. Part of the job of constructors and setters is to validate input. That can include things like:
public void setPrice(double price) {
if (price < 0.0d) {
throw new IllegalArgumentException("price cannot be negative " + price);
}
this.price = price;
}
and
public void setName(String name) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
}
You could use wrapper functions for the actual check and throwing the exception.
Non-reflective solution for Java 8, without using a series of if's, would be to stream all fields and check for nullness:
return Stream.of(id, name).allMatch(Objects::isNull);
This remains quite easy to maintain while avoiding the reflection hammer.
This will return true for null attributes.
Maybe check Hibernate Validator 4.0, the Reference Implementation of the JSR 303: Bean Validation.
This is an example of an annotated class:
public class Address {
#NotNull
private String line1;
private String line2;
private String zip;
private String state;
#Length(max = 20)
#NotNull
private String country;
#Range(min = -2, max = 50, message = "Floor out of range")
public int floor;
...
}
For an introduction, see Getting started with JSR 303 (Bean Validation) – part 1 and part 2 or the "Getting started" section of the reference guide which is part of the Hibernate Validator distribution.
You can create a function that returns a boolean value and checks every attribute. You can call that function to do the job for you.
Alternatively, you can initialize the object with default values. That way there is no need for you to do any checking.
I don't have enough context to give you a correct answer, but I'll suggest you to make you code immutable as much as possible. Use public final fields. No more getters or setters : every field has to be defined by the constructor. Your code is shorter, more readable and prevents you from writing code with side effects.
It doesn't prevent you from passing null arguments to your constructor though... You can still check every argument as suggested by #cletus, but I'll suggest you to throw IllegalArgumentException instead of NullPointerException that doesn't give no new hint about what you've done.
Anyway, that's what I do as much as I can and it improved my code (readability, stability) to a great extend. Everyone in my team does so and we are very happy with that. We learned that when we try to write some erlang code where everything is immutable.
Hope this helps.
I tried this and it works without any issues to validate if the field is empty.
I have answered your question partially as I haven't personally tried to add default values to attributes
if(field.getText()!= null && !field.getText().isEmpty())
Hope it helps
This is not to check for null, instead this will be helpful in converting an existing object to an empty object(fresh object). I dont know whether this is relevant or not, but I had such a requirement.
#SuppressWarnings({ "unchecked" })
static void emptyObject(Object obj)
{
Class c1 = obj.getClass();
Field[] fields = c1.getDeclaredFields();
for(Field field : fields)
{
try
{
if(field.getType().getCanonicalName() == "boolean")
{
field.set(obj, false);
}
else if(field.getType().getCanonicalName() == "char")
{
field.set(obj, '\u0000');
}
else if((field.getType().isPrimitive()))
{
field.set(obj, 0);
}
else
{
field.set(obj, null);
}
}
catch(Exception ex)
{
}
}
}

Is this class not a Java Bean?

I am trying to use existing Java classes to create a web service using Axis2.
When I send a request to the web service, Axis2 displays the following message:
[01 Nov 2012 16:37:05:244] classloader.BeanInfoCache: Unable to locate a BeanInfo cache for class ems.shared.Fti (stopClass=class java.lang.Object). This will negatively affect performance!
I'm not sure what that error means, but it makes me wonder if the ems.shared.Fti class doesn't satisfy all the requirements to being a Java Bean. Can you see anything wrong with this class?
package ems.shared;
import java.io.Serializable;
public class Fti implements Serializable
{
private static final long serialVersionUID = 7476379431395094501L;
public static final Fti UNDEFINED = new Fti(-1);
public static final Fti BROADCAST = new Fti((int) (Math.pow(2, 20) - 2));
private int fti;
public Fti() {
}
public Fti(int fti)
{
this.fti = fti;
}
public Fti(String fti)
{
try
{
this.fti = Integer.parseInt(fti);
}
catch (NumberFormatException e)
{
throw new IllegalArgumentException(fti + " is not a valid FTI");
}
}
public void setFti(int fti) {
this.fti = fti;
}
public int getFti() {
return fti;
}
public int asInt()
{
return this.fti;
}
#Override
public String toString()
{
return String.valueOf(fti);
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + fti;
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Fti other = (Fti) obj;
if (fti != other.fti)
return false;
return true;
}
}
BeanInfo is something separate. It was originally the mechanism by which a JavaBean would tell a Bean shell about itself, a la Visual Basic:
http://docs.oracle.com/cd/E23095_01/Platform.93/ATGProgGuide/html/s0503beaninfoexample01.html
BeanInfo instances are created by the JavaBean introspector (see the JRE Javadoc). As pointed out by duffymo, it is possible to provide the BeanInfo explicitly together with the JavaBean, in which case the introspector simply loads that BeanInfo. This is primarily used for UI components and is not mandatory. For a JavaBean that has no explicit BeanInfo, the introspector simply constructs the BeanInfo instance using reflection. This is what happens in your case.
The point is that the JRE doesn't cache BeanInfo objects. The reason is that it cannot do that without the risk of causing class loader leaks (see IZ67457 for an example of a bug caused by an attempt to cache these objects in certain versions of the IBM JRE). However, constructing a BeanInfo object using reflection is a costly operation. Therefore Axis2 has its own BeanInfo cache. That cache is carefully designed to avoid class loader leaks.
The message that you get (which BTW is a warning, not an error) simply says that in your case Axis2 is not able to use a cached BeanInfo object. There are two possible reasons for that: either you are in a scenario where it is impossible to cache the BeanInfo object without potentially causing a class loader leak, or you are in a scenario where the BeanInfo object could be cached without causing a class loader leak but that is not supported by the BeanInfo cache (i.e. you are encountering a limitation in the cache implementation).
To analyze this further, you need to determine which class loader loads the Fti class, which class loader loads the BeanInfoCache class (i.e. the axis2-kernel JAR) and how these class loaders are related to each other (e.g. are they related by a parent-child relationship).

Java Beans, BeanUtils, and the Boolean wrapper class

I'm using BeanUtils to manipulate Java objects created via JAXB, and I've run into an interesting issue. Sometimes, JAXB will create a Java object like this:
public class Bean {
protected Boolean happy;
public Boolean isHappy() {
return happy;
}
public void setHappy(Boolean happy) {
this.happy = happy;
}
}
The following code works just fine:
Bean bean = new Bean();
BeanUtils.setProperty(bean, "happy", true);
However, attempting to get the happy property like so:
Bean bean = new Bean();
BeanUtils.getProperty(bean, "happy");
Results in this exception:
Exception in thread "main" java.lang.NoSuchMethodException: Property 'happy' has no getter method in class 'class Bean'
Changing everything to a primitive boolean allows both the set and get call to work. I don't have this option, however, since these are generated classes. I assume this happens because the Java Bean libraries only consider an is<name> method to represent a property if the return type is a primitive boolean, and not the wrapper type Boolean. Does anyone have a suggestion as to how to access properties like these through BeanUtils? Is there some kind of workaround I can use?
Finally I've found legal confirmation:
8.3.2 Boolean properties
In addition, for boolean properties, we allow a getter method to match the pattern:
public boolean is<PropertyName>();
From JavaBeans specification. Are you sure you haven't came across JAXB-131 bug?
Workaround to handle Boolean isFooBar() case with BeanUtils
Create new BeanIntrospector
private static class BooleanIntrospector implements BeanIntrospector{
#Override
public void introspect(IntrospectionContext icontext) throws IntrospectionException {
for (Method m : icontext.getTargetClass().getMethods()) {
if (m.getName().startsWith("is") && Boolean.class.equals(m.getReturnType())) {
String propertyName = getPropertyName(m);
PropertyDescriptor pd = icontext.getPropertyDescriptor(propertyName);
if (pd == null)
icontext.addPropertyDescriptor(new PropertyDescriptor(propertyName, m, getWriteMethod(icontext.getTargetClass(), propertyName)));
else if (pd.getReadMethod() == null)
pd.setReadMethod(m);
}
}
}
private String getPropertyName(Method m){
return WordUtils.uncapitalize(m.getName().substring(2, m.getName().length()));
}
private Method getWriteMethod(Class<?> clazz, String propertyName){
try {
return clazz.getMethod("get" + WordUtils.capitalize(propertyName));
} catch (NoSuchMethodException e) {
return null;
}
}
}
Register BooleanIntrospector:
BeanUtilsBean.getInstance().getPropertyUtils().addBeanIntrospector(new BooleanIntrospector());
you can just create second getter with SET - sufix as workaround :)

Java bean testing framework

Is there a framework or library available that, when given a JavaBean, will "put it through its paces," i.e., test all the getters and setters, validate that a property matches the getters and setters, etc.?
Personally, I don't think that's the hardest part of testing. It'd be possible to do via reflection, but that's not what makes testing worthwhile.
The hard part is figuring out all the possible inputs, for "happy path" and erroneous situations, making sure that exceptions are thrown when they should be, etc.
Your Java Bean should be implementing equals and hashCode. I'd worry more about tests to check the equals contract: null equals, reflexive, symmetric, transitive, and not equals. Those aren't trivial.
Getters and setters are the least of your problems. When people talk about code coverage standards of 70% or better they often say that getters and setters can be left out.
While I agree that there are bigger problems to solve, there are cases for testing Java bean methods. Large teams teams working on large codebases can run into problems. I've seen several cases of copy/paste error leading to getters or setters working on the wrong property. Forgetfulness can lead to hashCode and equals methods becoming inconsistent. Finding bugs in this simple code can be very frustrating.
Bean Matchers is a library that can help in this regard. It provides a series of Hamcrest matchers for reflectively testing Java beans. For example:
#Test
public void testBean() {
assertThat(MyBean.class, allOf(
hasValidBeanConstructor(),
hasValidGettersAndSetters(),
hasValidBeanHashCode(),
hasValidBeanEquals(),
hasValidBeanToString()
));
}
Take a look at Reflection Test Utilities:
http://code.google.com/p/rtu/
Although if you're testing generated methods (based on fields in a class) it may not be worth it.
If you're not looking like something more fancy like http://commons.apache.org/validator/ I would recommend to write your own. Personally I don't like pure data holding objects without any behaviour - it's not very good design. So if I'm not forced to work with such objects (by working with j2ee f. e.), I try to get rid of them.
You could try http://oval.sourceforge.net/ Oval it allows you to use annotations on your beans and then execute a validate method. It's not fully JSR303 compliant. If you want to use something fully compliant you should check out the Hibernate Validator.
Like the post above states definitely check out apache commons validator.
Answering this in 2021 because sadly, this problem still exists.
Beans add up to the code base and have a very negative impact if your DevOps pipelines are imposing coverage restrictions on repos. There are two ways to overcome it.
Exclude the beans ( which I would say should not be done).
Write test cases for beans ( which is the most pathetic thing that we as a developer can do to waste our time :( ).
And in most cases, you will end up writing test cases for beans.
I have written this simple Utility/test case that uses reflection and can allow you to increase the Junit code coverage and save your time.
Bean under test: City
package com.test.beans;
import java.util.List;
/**
* #author ameena
*
*/
public class City {
private int postOffices;
private int jurdictaionAreas;
private double areaInSqMeter;
private long population;
private List<City> neighbourCities;
private boolean metro;
public int getJurdictaionAreas() {
return jurdictaionAreas;
}
public void setJurdictaionAreas(int jurdictaionAreas) {
this.jurdictaionAreas = jurdictaionAreas;
}
public double getAreaInSqMeter() {
return areaInSqMeter;
}
public void setAreaInSqMeter(double areaInSqMeter) {
this.areaInSqMeter = areaInSqMeter;
}
public long getPopulation() {
return population;
}
public void setPopulation(long population) {
this.population = population;
}
public int getPostOffices() {
return postOffices;
}
public void setPostOffices(int postOffices) {
this.postOffices = postOffices;
}
public List<City> getNeighbourCities() {
return neighbourCities;
}
public void setNeighbourCities(List<City> neighbourCities) {
this.neighbourCities = neighbourCities;
}
public boolean isMetro() {
return metro;
}
public void setMetro(boolean metro) {
this.metro = metro;
}
}
The class to automate the bean testing
package com.test.beans;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.jupiter.api.Assertions.fail;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
/**
* #author ameena
*
*/
class BeanTest {
public void invokeSetter(Object obj, String propertyName, Object variableValue)
{
PropertyDescriptor propDescriptor;
try {
propDescriptor = new PropertyDescriptor(propertyName, obj.getClass());
Method setter = propDescriptor.getWriteMethod();
try {
setter.invoke(obj,variableValue);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
fail(e.getMessage());
}
} catch (IntrospectionException e) {
e.printStackTrace();
fail(e.getMessage());
}
}
public Object invokeGetter(Object obj, String variableName)
{
Object returnValue = null;
try {
PropertyDescriptor pd = new PropertyDescriptor(variableName, obj.getClass());
Method getter = pd.getReadMethod();
returnValue = getter.invoke(obj);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | IntrospectionException e) {
e.printStackTrace();
fail(e.getMessage());
}
return returnValue;
}
private <T extends Object> void validateGettersSetters(List<T> objects) {
for (T t : objects) {
Class<?> aClass = t.getClass();
for (java.lang.reflect.Field field : aClass.getDeclaredFields()) {
System.out.println(field);
Class<?> c = field.getType();
if (c == String.class) {
invokeSetter(t, field.getName(), "dummy");
assertEquals("dummy", (invokeGetter(t, field.getName())));
} else if (c == Integer.class || c == int.class) {
invokeSetter(t, field.getName(), 1);
assertEquals(1, (invokeGetter(t, field.getName())));
}else if (c == Double.class || c == double.class) {
invokeSetter(t, field.getName(), 1d);
assertEquals(1d, (invokeGetter(t, field.getName())));
}else if (c == Long.class || c == long.class) {
invokeSetter(t, field.getName(), 1l);
assertEquals(1l, (invokeGetter(t, field.getName())));
}else if (c == Boolean.class || c == boolean.class) {
invokeSetter(t, field.getName(), true);
assertEquals(true, (invokeGetter(t, field.getName())));
}else if (c == List.class){
//Now based on your bean and filed name
switch(field.getName()) {
case "neighbourCities" :
invokeSetter(t, field.getName(), new ArrayList<City>());
assertNotNull(invokeGetter(t, field.getName()));
break;
}
}
}
}
}
#Test
void testBean() {
List<Object> objects = new ArrayList<>();
objects.add(new City());
validateGettersSetters(objects);
}
}
Nothing fancy, but it saved me for writing test cases for 23 beans :)
Regards
Amit Meena
I guess this library is the answer to your question:
http://outsidemybox.github.com/testUtils/
it tests all the bean's initial values, the setters, the getters, hashCode(), equals() and toString().
All you have to do is define a map of default and non default property/value.
It can also test objects that are beans with additional non default constructors.

Categories