blob: 04e3f81bde227322e80b0e75661dea0920b80bcc [file] [log] [blame]
/**
* Copyright (C) 2006 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.inject;
import junit.framework.TestCase;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.annotation.Retention;
import java.lang.annotation.Annotation;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* @author crazybob@google.com (Bob Lee)
*/
public class FactoryTest extends TestCase {
public void testParameterIndex() throws ContainerCreationException {
ContainerBuilder cb = new ContainerBuilder();
cb.bind(Zero.class).to(new Generator<Zero>() {
public Zero generate(Context context) {
assertEquals(0, context.getParameterIndex());
return new Zero();
}
});
cb.bind(One.class).to(new Generator<One>() {
public One generate(Context context) {
assertEquals(1, context.getParameterIndex());
return new One();
}
});
cb.bind(NegativeOne.class).to(new Generator<NegativeOne>() {
public NegativeOne generate(Context context) {
assertEquals(-1, context.getParameterIndex());
return new NegativeOne();
}
});
Container c = cb.create();
A a = c.getFactory(A.class).get();
assertNotNull(a.negativeOne);
assertTrue(a.initCalled);
}
static class A {
@Inject
NegativeOne negativeOne;
boolean initCalled;
@Inject void init(Zero zero, One one) {
assertNotNull(zero);
assertNotNull(one);
initCalled = true;
}
}
static class Zero {}
static class One {}
static class NegativeOne {}
@Retention(RUNTIME)
@Binder @interface FooAnnotation {}
@Retention(RUNTIME)
@Binder @interface BarAnnotation {}
@Retention(RUNTIME)
@Binder @interface TeeAnnotation1 {}
@Retention(RUNTIME)
@Binder @interface TeeAnnotation2 {}
@Retention(RUNTIME)
@Binder @interface BobAnnotation1 {}
@Retention(RUNTIME)
@Binder @interface BobAnnotation2 {}
public void testInjection() throws Exception {
ContainerBuilder cb = new ContainerBuilder(Stage.PRODUCTION);
// Called from getInstance().
cb.bind(Foo.class)
.annotatedWith(FooAnnotation.class)
.to(createFactory(Foo.class, FooAnnotation.class, null));
// Called during preloading.
cb.bind(Bar.class)
.annotatedWith(BarAnnotation.class)
.to(createFactory(Bar.class, BarAnnotation.class, null))
.in(Scopes.CONTAINER);
cb.bind(Tee.class)
.annotatedWith(TeeAnnotation1.class)
.to(createFactory(Tee.class, TeeAnnotation1.class,
Bar.class.getDeclaredConstructor(Tee.class)));
cb.bind(Tee.class)
.annotatedWith(TeeAnnotation2.class)
.to(createFactory(Tee.class, TeeAnnotation2.class,
Bar.class.getDeclaredField("tee2")));
final Method execute = Tee.class.getDeclaredMethod(
"execute", Bob.class, Bob.class);
cb.bind(Bob.class).annotatedWith(BobAnnotation1.class).to(
createFactory(Bob.class, BobAnnotation1.class, execute));
cb.bind(Bob.class).annotatedWith(BobAnnotation2.class).to(
createFactory(Bob.class, BobAnnotation2.class, execute));
Container c = cb.create();
Foo foo = c.getFactory(Key.get(Foo.class, FooAnnotation.class)).get();
assertNotNull(foo.bar);
assertNotNull(foo.bar.tee1);
assertNotNull(foo.bar.tee2);
assertNotNull(foo.bar.tee1.bob1);
assertNotNull(foo.bar.tee1.bob2);
assertNotNull(foo.bar.tee2.bob1);
assertNotNull(foo.bar.tee2.bob2);
}
<T> Generator<T> createFactory(
final Class<T> type, final Class<? extends Annotation> annotationType,
final Member expectedMember) {
return new Generator<T>() {
public T generate(Context context) {
assertEquals(expectedMember, context.getMember());
assertEquals(type, context.getKey().getType().getType());
return context.getContainer().getFactory(type).get();
}
};
}
static class Foo {
final Bar bar;
@Inject Foo(@BarAnnotation Bar bar) {
this.bar = bar;
}
}
static class Bar {
@Inject @TeeAnnotation2 Tee tee2;
final Tee tee1;
@Inject Bar(@TeeAnnotation1 Tee tee1) {
this.tee1 = tee1;
}
}
static class Tee {
Bob bob1, bob2;
@Inject void execute(
@BobAnnotation1 Bob bob1,
@BobAnnotation2 Bob bob2) {
this.bob1 = bob1;
this.bob2 = bob2;
}
}
static class Bob {}
}