package br.com.caelum.iogi.parameters;
import br.com.caelum.iogi.fixtures.TwoArguments;
import br.com.caelum.iogi.reflection.ClassConstructor;
import br.com.caelum.iogi.reflection.Target;
import br.com.caelum.iogi.spi.ParameterNamesProvider;
import com.google.common.collect.Lists;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.List;
import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.*;
public class ParametersTests {
private final Mockery context = new Mockery();
@Test
public void namedAfterReturnsAParameterWhoseFirstComponentIsTheSameAsTheTargetName() throws Exception {
final Target<Object> target = Target.create(Object.class, "name");
final Parameter correct = new Parameter("name.asdf", "");
final Parameter incorrect = new Parameter("otherName.asdf", "");
final Parameters parameters = new Parameters(correct, incorrect);
assertEquals(correct, parameters.namedAfter(target));
}
@Test
public void ifThereIsAParameterWithTheSameWholeNameAsTheTargetNameThenItWillBeReturnedByNamedAfter() throws Exception {
final Target<Object> target = Target.create(Object.class, "name");
final Parameter correct = new Parameter("name", "");
final Parameter incorrect = new Parameter("otherName", "");
final Parameters parameters = new Parameters(correct, incorrect);
assertEquals(correct, parameters.namedAfter(target));
}
@Test(expected=IllegalStateException.class)
public void namedAfterWillThrowAnExceptionIfThereIsMoreThanOneParameterBegginingWithTheTargetName() throws Exception {
final Target<Object> target = Target.create(Object.class, "name");
final Parameter one = new Parameter("name", "one");
final Parameter two = new Parameter("name", "two");
final Parameters parameters = new Parameters(one, two);
parameters.namedAfter(target);
}
@Test
public void namedAfterWillReturnAnEmptyParameterIfThereIsNoParameterBegginingWithTheTargetName() throws Exception {
final Target<Object> target = Target.create(Object.class, "name");
final Parameter one = new Parameter("fizzble", "one");
final Parameter two = new Parameter("foozble", "two");
final Parameters parameters = new Parameters(one, two);
final Parameter found = parameters.namedAfter(target);
assertEquals("", found.getValue());
}
@Test
public void parametersNotUsedByAConstructorAreThoseWhoseFirstComponentsDontMatchWithTheConstructorArgumentNames() throws Exception {
final Parameters parameters = parametersNamed("foo", "one", "two", "fizzle");
final Constructor<TwoArguments> constructorWithParametersNamedOneAndTwo = TwoArguments.class.getDeclaredConstructor(int.class, int.class);
final ClassConstructor constructor = new ClassConstructor(constructorWithParametersNamedOneAndTwo, providingNames("one", "two"));
final Parameters notUsed = parameters.notUsedBy(constructor);
assertThat(notUsed.getParametersList(), containsInAnyOrder(new Parameter("foo", ""), new Parameter("fizzle", "")));
}
@Test
public void parametersForTargetAreThoseWhoseFirstNameComponentMatchTheTargetName() throws Exception {
Parameter matchingParameter = new Parameter("matchingName.foo", "42");
Parameter notMatchingParameter = new Parameter("notMatching.foo", "123");
Parameters parameters = new Parameters(matchingParameter, notMatchingParameter);
List<Parameter> obtained = parameters.forTarget(Target.create(Object.class, "matchingName"));
assertEquals(asList(matchingParameter), obtained);
}
@Test
public void ifThereAreNoMatchingParametersThenParametersForTargetReturnsAnEmptyList() throws Exception {
Parameter notMatchingParameter = new Parameter("notMatching.foo", "123");
Parameters parameters = new Parameters(notMatchingParameter);
List<Parameter> obtained = parameters.forTarget(Target.create(Object.class, "matchingName"));
assertTrue(obtained.isEmpty());
}
@Test
public void parametersHaveParametersRelatedToATargetWhenAtLeastOneParameterHasTheTargetNameAsItsFirstSegment() throws Exception {
Parameters parameters = parametersNamed("name.foo");
assertTrue(parameters.hasRelatedTo(Target.create(Object.class, "name")));
assertFalse(parameters.hasRelatedTo(Target.create(Object.class, "other")));
}
private Parameters parametersNamed(final String... names) {
final List<Parameter> params = Lists.newArrayList();
for (final String name : names) {
params.add(new Parameter(name, ""));
}
return new Parameters(params);
}
private ParameterNamesProvider providingNames(final String... names) {
final ParameterNamesProvider mockParameterNamesProvider = context.mock(ParameterNamesProvider.class);
context.checking(new Expectations() {
{
allowing(mockParameterNamesProvider).lookupParameterNames(with(any(AccessibleObject.class)));
will(returnValue(Arrays.asList(names)));
}
});
return mockParameterNamesProvider;
}
}