There are two ways for unit testing Stripes applications: directly instantiate the ActionBean or use Mock objects. But neither provided the “feel” I wanted to have for my unit tests.
In my tests I wanted to use a URL only to call the right ActionBean. So, my own solution is a mixture between mocking and direct instantiation. in my tests I use the following method to create an ActionBean:
protected <T extends ActionBean> T createActionBean(String url, Class<T> clazz, Map<String, Object> params)
throws Exception {
T instance = clazz.newInstance();
injectMembers(instance);
UrlBindingFactory factory = UrlBindingFactory.getInstance();
factory.addBinding(clazz, UrlBindingFactory.parseUrlBinding(clazz));
UrlBinding binding = factory.getBinding(url);
Method method = null;
for (UrlBindingParameter parameter : binding.getParameters()) {
String name = parameter.getName();
if (name.equals("$event")) {
if (parameter.getValue() != null) {
method = clazz.getDeclaredMethod(parameter.getValue());
}
}
else {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
Validate validate = field.getAnnotation(Validate.class);
Object value = null;
if (validate != null) {
Class<? extends TypeConverter> converter = validate.converter();
if (converter != null) {
value = converter.newInstance().convert(parameter.getValue(),
field.getType(),
new ArrayList<ValidationError>());
}
}
if (value == null && parameter.getValue() != null) {
if (Number.class.isAssignableFrom(field.getType())) {
value = DecimalFormat.getNumberInstance().parse(parameter.getValue());
}
}
field.set(instance, value);
}
}
if (params != null) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
Field field = clazz.getDeclaredField(entry.getKey());
field.setAccessible(true);
field.set(instance, entry.getValue());
}
}
if (method == null) {
for (Method m : clazz.getDeclaredMethods()) {
if (m.isAnnotationPresent(DefaultHandler.class)) {
method = m;
}
}
}
if (method != null) {
method.invoke(instance);
}
return instance;
}
What is still missing: I’d like to use the Stripes provided mock object classes more to support all types of parameters, validations etc.