Created
April 24, 2012 17:06
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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