package in.partake.model.dto;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isIn;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeThat;
import in.partake.AbstractPartakeTestWithApplication;
import in.partake.model.fixture.TestDataProvider;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.List;
import java.util.UUID;
import org.codehaus.jackson.node.ObjectNode;
import org.junit.Assert;
import org.junit.Test;
import play.Logger;
public abstract class AbstractPartakeModelTest<T extends PartakeModel<T>> extends AbstractPartakeTestWithApplication {
protected abstract TestDataProvider<T> getTestDataProvider();
protected abstract T copy(T t);
/**
* freezeしてから破壊的メソッドを実行するとUnsupportedOperationExceptionが投げられることを保証する。
* freezeしていない時に正しく実行できることの保証は、各サブクラスのテストが担う。
* @author skypencil(@eller86)
*/
@Test
public final void testToCheckFrozen() throws Exception {
final T model = getTestDataProvider().create().freeze();
for (Method method : model.getClass().getMethods()) {
if (!checkDestructiveMethod(method) || method.getDeclaringClass().equals(Object.class))
continue;
Logger.debug(String.format("Test for %s#%s starts.", model.getClass().getName(), method.getName()));
Object[] args = createArgsFor(method);
try {
method.invoke(model, args);
Assert.fail(method.getName() + " should throw UnsupportedOperationException but doesn't throw.");
} catch (InvocationTargetException e) {
if (!e.getTargetException().getClass().equals(UnsupportedOperationException.class))
throw new AssertionError(e);
}
}
}
@Test
public final void testToCheckSetterWhenNotFrozen() throws Exception {
final T model = getTestDataProvider().create();
for (Method method : model.getClass().getMethods()) {
if (!checkDestructiveMethod(method) || method.getDeclaringClass().equals(Object.class))
continue;
Object[] args = createArgsFor(method);
method.invoke(model, args);
}
}
@Test
public final void testToCheckCopy() throws Exception {
final T original = getTestDataProvider().create();
final T copied = copy(original);
assertThat(copied.equals(original), is(true));
}
@Test
public final void testToCheckEquals() throws Exception {
List<T> samples = getTestDataProvider().createSamples();
for (int i = 1; i < samples.size(); ++i) {
assertThat("Index " + String.valueOf(i) + " is the same as index 0.",
samples.get(0).equals(samples.get(i)), is(false));
}
assertThat(samples.get(0).equals(null), is(false));
}
@Test
public final void testToCheckJSON() throws Exception {
List<T> samples = getTestDataProvider().createSamples();
Constructor<?> ctor = samples.get(0).getClass().getConstructor(ObjectNode.class);
assumeThat(samples.get(0).getClass(), not(isIn(new Object[] { UserImage.class, UserThumbnail.class })));
for (T t : samples) {
Object created = ctor.newInstance(t.toJSON());
assertThat(t.equals(created), is(true));
}
}
// ----------------------------------------------------------------------
private Object[] createArgsFor(final Method m) {
final Type[] types = m.getGenericParameterTypes();
final Object[] result = new Object[types.length];
for (int i = 0; i < types.length; ++i) {
Type type = types[i];
result[i] = createArg(type);
}
return result;
}
private Object createArg(Type c) {
if (c.equals(int.class)) {
return Integer.valueOf(0);
} else if (c.equals(long.class)) {
return Long.valueOf(0L);
} else if (c.equals(boolean.class)) {
return Boolean.FALSE;
} else if (c.equals(char.class)) {
return Character.valueOf((char)0);
} else if (c.equals(byte.class)) {
return Byte.valueOf((byte)0);
} else if (c.equals(short.class)) {
return Short.valueOf((short)0);
} else if (c.equals(float.class)) {
return Float.valueOf(0.0f);
} else if (c.equals(double.class)) {
return Double.valueOf(0.0d);
} else if (c.equals(UUID.class)) {
return new UUID(0, 0);
} else {
return null;
}
}
private boolean checkDestructiveMethod(final Method m) {
return m.getReturnType().equals(Void.TYPE) && !Modifier.isStatic(m.getModifiers());
}
}