package br.com.caelum.iogi.reflection;
import br.com.caelum.iogi.DependenciesInjector;
import br.com.caelum.iogi.Instantiator;
import br.com.caelum.iogi.conversion.StringConverter;
import br.com.caelum.iogi.parameters.Parameter;
import br.com.caelum.iogi.parameters.Parameters;
import br.com.caelum.iogi.spi.ParameterNamesProvider;
import br.com.caelum.iogi.util.NullDependencyProvider;
import com.google.common.collect.ImmutableList;
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.Collection;
import static org.junit.Assert.assertEquals;
public class ClassConstructorTests {
private final Constructor<Foo> fooConstructor;
private final Instantiator<?> primitiveInstantiator;
private final Mockery context;
public ClassConstructorTests() throws SecurityException, NoSuchMethodException {
fooConstructor = Foo.class.getConstructor(String.class, String.class);
primitiveInstantiator = new StringConverter();
context = new Mockery();
}
@Test
public void canInstantiateFromArgumentNames() throws Exception {
final ImmutableList<Parameter> parameters = ImmutableList.<Parameter>builder().add(new Parameter("two", "b")).add(new Parameter("one", "a")).build();
final DependenciesInjector nullDependenciesInjector = new DependenciesInjector(new NullDependencyProvider());
final Constructors.FilledConstructor constructor = new Constructors.FilledConstructor(
new ClassConstructor(fooConstructor, providingNames("one", "two")),
new Parameters(parameters),
nullDependenciesInjector);
@SuppressWarnings("unchecked")
NewObject newObject = constructor.instantiate((Instantiator<Object>) primitiveInstantiator);
final Foo foo = (Foo) newObject.value();
assertEquals("a", foo.getOne());
assertEquals("b", foo.getTwo());
}
@Test
public void sizeIsTheNumberOfArguments() throws Exception {
final ClassConstructor constructor = new ClassConstructor(fooConstructor, providingNames("one", "two"));
assertEquals(2, constructor.size());
}
@Test
public void notFulfilledByParametersWillReturnTargetsForParametersWhoseNamesArentFoundInTheParameters() throws Exception {
final ClassConstructor constructor = new ClassConstructor(fooConstructor, providingNames("one", "two"));
final Parameter aParameter = new Parameter("two", "");
final Collection<Target<?>> unfulfilled = constructor.notFulfilledBy(new Parameters(aParameter));
assertEquals(1, unfulfilled.size());
assertEquals(Target.create(String.class, "one"), unfulfilled.iterator().next());
}
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;
}
public static class Foo {
private final String one;
private final String two;
public Foo(final String one, final String two) {
this.one = one;
this.two = two;
}
public String getOne() {
return one;
}
public String getTwo() {
return two;
}
}
}