Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tknerr/2481533 to your computer and use it in GitHub Desktop.
Save tknerr/2481533 to your computer and use it in GitHub Desktop.
cucumber-jvm: subclassing vs. wrapping in order to specify an xstream converter for runtime classes
Feature: Foo Feature
Scenario: do some foo
Given I have some foo named "MyFoo"
Scenario: do some foo with data table first
Given I have some foo's in a data table:
| foo |
| MyFooToo |
Given I have some foo named "MyFoo"
package features.foo.holder;
import java.lang.reflect.Constructor;
import java.util.List;
import junit.framework.Assert;
import cucumber.annotation.en.Given;
import cucumber.runtime.xstream.annotations.XStreamConverter;
import cucumber.runtime.xstream.converters.basic.AbstractSingleValueConverter;
import cucumber.runtime.xstream.converters.extended.ToStringConverter;
/**
* shows how you can make the parameter conversion work for an external {@link ExternalFinalFoo} which
* you can not annotate with {@link XStreamConverter} for any reason and which is final, i.e.
* sub-classing {@link ExternalFinalFoo} does not work too, thus you have to fall back to a 'holder idiom'.
*/
public class FooStepDefsWithExternalFooAndHolderIdiom {
@Given("^I have some foo named \"([^\"]*)\"$")
public void I_have_some_foo_named(ExternalFinalFooHolder fooHolder) {
Assert.assertNotNull(fooHolder.getObject().getName());
}
@Given("^I have some foo's in a data table:$")
public void I_have_some_foo_s_in_a_data_table(List<ExternalFinalFooInTable> foosInTable) {
for (ExternalFinalFooInTable fooInTable : foosInTable) {
Assert.assertNotNull(fooInTable.foo.getName());
}
}
public static class ExternalFinalFooInTable {
@XStreamConverter(ToStringConverter.class)
public ExternalFinalFoo foo;
}
@XStreamConverter(ToStringConverter.class)
public static class ExternalFinalFooHolder extends ConvertingHolder<ExternalFinalFoo> {
public ExternalFinalFooHolder(String name) {
super(name, ExternalFinalFoo.class, ToStringConverter.class);
}
}
/**
* base class implementing the holder idiom and converting to the
* given type with the given converter.
*/
public static class ConvertingHolder<T> {
private final T object;
@SuppressWarnings("unchecked")
public ConvertingHolder(String string, Class<T> type,
Class<? extends AbstractSingleValueConverter> converterClazz) {
try {
Constructor<?> converterCtor = converterClazz.getConstructors()[0];
AbstractSingleValueConverter converter = null;
if (converterCtor.getParameterTypes().length == 1) {
converter = (AbstractSingleValueConverter) converterCtor.newInstance(type);
} else if (converterCtor.getParameterTypes().length == 0) {
converter = (AbstractSingleValueConverter) converterCtor.newInstance();
}
assert converter != null;
assert converter.canConvert(type);
object = (T) converter.fromString(string);
} catch (Exception e) {
throw new RuntimeException("could not convert", e);
}
}
public T getObject() {
return object;
}
@Override
public String toString() {
return object.toString();
}
}
}
package features.foo.subclass;
import java.util.List;
import junit.framework.Assert;
import cucumber.annotation.en.Given;
import cucumber.runtime.xstream.annotations.XStreamConverter;
import cucumber.runtime.xstream.converters.extended.ToStringConverter;
/**
* shows how you can make the parameter conversion work for an external {@link ExternalFoo} (which
* you can not annotate with {@link XStreamConverter} for any reason) using sub-classing.
*/
public class FooStepDefsWithExternalFooAndSubclassing {
@Given("^I have some foo named \"([^\"]*)\"$")
public void I_have_some_foo_named(ExternalFooSubclass foo) {
Assert.assertNotNull(foo.getName());
}
@Given("^I have some foo's in a data table:$")
public void I_have_some_foo_s_in_a_data_table(List<ExternalFooInTable> foosInTable) {
for (ExternalFooInTable fooInTable : foosInTable) {
Assert.assertNotNull(fooInTable.foo.getName());
}
}
public static class ExternalFooInTable {
@XStreamConverter(ToStringConverter.class)
public ExternalFoo foo;
}
@XStreamConverter(ToStringConverter.class)
public static class ExternalFooSubclass extends ExternalFoo {
public ExternalFooSubclass(String name) {
super(name);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment