blob: a526c936c9de562dbc9151e5d2ade890925174c6 [file] [log] [blame]
/*
* Copyright (C) 2008 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 static com.google.inject.Asserts.assertContains;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import junit.framework.TestCase;
/**
* This test verifies the ways things are injected (ie. getInstance(), injectMembers(), bind to
* instance, and bind to provider instance) for all states of optional bindings (fields, methods,
* multiple-argument methods, provider fields, provider methods, constructors).
*
* @author jessewilson@google.com (Jesse Wilson)
*/
public class OptionalBindingTest extends TestCase {
private static final A injectA = new A() {};
private static final B injectB = new B() {};
private static final C injectC = new C() {};
private static final D injectD = new D() {};
private static final E injectE = new E() {};
private static final F injectF = new F() {};
private static final G injectG = new G() {};
private Module everythingModule =
new AbstractModule() {
@Override
protected void configure() {
bind(A.class).toInstance(injectA);
bind(B.class).toInstance(injectB);
bind(C.class).toInstance(injectC);
bind(D.class).toInstance(injectD);
bind(E.class).annotatedWith(Names.named("e")).toInstance(injectE);
bind(F.class).toInstance(injectF);
bind(G.class).toInstance(injectG);
}
};
private Module partialModule =
new AbstractModule() {
@Override
protected void configure() {
bind(C.class).toInstance(new C() {});
}
};
private Module toInstanceModule =
new AbstractModule() {
@Override
protected void configure() {
bind(HasOptionalInjections.class).toInstance(new HasOptionalInjections());
}
};
private Module toProviderInstanceModule =
new AbstractModule() {
@Override
protected void configure() {
bind(HasOptionalInjections.class).toProvider(new HasOptionalInjectionsProvider());
}
};
private Module toProviderModule =
new AbstractModule() {
@Override
protected void configure() {
bind(HasOptionalInjections.class).toProvider(HasOptionalInjectionsProvider.class);
}
};
public void testEverythingInjectorGetInstance() {
Guice.createInjector(everythingModule)
.getInstance(HasOptionalInjections.class)
.assertEverythingInjected();
}
public void testPartialInjectorGetInstance() {
Guice.createInjector(partialModule)
.getInstance(HasOptionalInjections.class)
.assertNothingInjected();
}
public void testNothingInjectorGetInstance() {
Guice.createInjector().getInstance(HasOptionalInjections.class).assertNothingInjected();
}
public void testEverythingInjectorInjectMembers() {
HasOptionalInjections instance = new HasOptionalInjections();
Guice.createInjector(everythingModule).injectMembers(instance);
instance.assertEverythingInjected();
}
public void testPartialInjectorInjectMembers() {
HasOptionalInjections instance = new HasOptionalInjections();
Guice.createInjector(partialModule).injectMembers(instance);
instance.assertNothingInjected();
}
public void testNothingInjectorInjectMembers() {
HasOptionalInjections instance = new HasOptionalInjections();
Guice.createInjector().injectMembers(instance);
instance.assertNothingInjected();
}
public void testEverythingInjectorToInstance() {
Guice.createInjector(everythingModule, toInstanceModule)
.getInstance(HasOptionalInjections.class)
.assertEverythingInjected();
}
public void testPartialInjectorToInstance() {
Guice.createInjector(partialModule, toInstanceModule)
.getInstance(HasOptionalInjections.class)
.assertNothingInjected();
}
public void testNothingInjectorToInstance() {
Guice.createInjector(toInstanceModule)
.getInstance(HasOptionalInjections.class)
.assertNothingInjected();
}
public void testEverythingInjectorToProviderInstance() {
Guice.createInjector(everythingModule, toProviderInstanceModule)
.getInstance(HasOptionalInjections.class)
.assertEverythingInjected();
}
public void testPartialInjectorToProviderInstance() {
Guice.createInjector(partialModule, toProviderInstanceModule)
.getInstance(HasOptionalInjections.class)
.assertNothingInjected();
}
public void testNothingInjectorToProviderInstance() {
Guice.createInjector(toProviderInstanceModule)
.getInstance(HasOptionalInjections.class)
.assertNothingInjected();
}
public void testEverythingInjectorToProvider() {
Guice.createInjector(everythingModule, toProviderModule)
.getInstance(HasOptionalInjections.class)
.assertEverythingInjected();
}
public void testPartialInjectorToProvider() {
Guice.createInjector(partialModule, toProviderModule)
.getInstance(HasOptionalInjections.class)
.assertNothingInjected();
}
public void testNothingInjectorToProvider() {
Guice.createInjector(toProviderModule)
.getInstance(HasOptionalInjections.class)
.assertNothingInjected();
}
static class HasOptionalInjections {
A originalA = new A() {};
@Inject(optional = true)
A a = originalA; // field injection
B b; // method injection with one argument
C c; // method injection with two arguments
D d; // method injection with two arguments
E e; // annotated injection
@Inject(optional = true)
Provider<F> fProvider; // provider
Provider<G> gProvider; // method injection of provider
boolean invoked0, invoked1, invoked2, invokedAnnotated, invokeProvider;
@Inject(optional = true)
void methodInjectZeroArguments() {
invoked0 = true;
}
@Inject(optional = true)
void methodInjectOneArgument(B b) {
this.b = b;
invoked1 = true;
}
@Inject(optional = true)
void methodInjectTwoArguments(C c, D d) {
this.c = c;
this.d = d;
invoked2 = true;
}
@Inject(optional = true)
void methodInjectAnnotated(@Named("e") E e) {
this.e = e;
invokedAnnotated = true;
}
@Inject(optional = true)
void methodInjectProvider(Provider<G> gProvider) {
this.gProvider = gProvider;
invokeProvider = true;
}
void assertNothingInjected() {
assertSame(originalA, a);
assertNull(b);
assertNull(c);
assertNull(d);
assertNull(e);
assertNull(fProvider);
assertNull(gProvider);
assertTrue(invoked0);
assertFalse(invoked1);
assertFalse(invoked2);
assertFalse(invokedAnnotated);
}
public void assertEverythingInjected() {
assertNotSame(injectA, originalA);
assertSame(injectA, a);
assertSame(injectB, b);
assertSame(injectC, c);
assertSame(injectD, d);
assertSame(injectE, e);
assertSame(injectF, fProvider.get());
assertSame(injectG, gProvider.get());
assertTrue(invoked0);
assertTrue(invoked1);
assertTrue(invoked2);
assertTrue(invokedAnnotated);
}
}
static class HasOptionalInjectionsProvider extends HasOptionalInjections
implements Provider<HasOptionalInjections> {
@Override
public HasOptionalInjections get() {
return this;
}
}
public void testOptionalConstructorBlowsUp() {
try {
Guice.createInjector().getInstance(HasOptionalConstructor.class);
fail();
} catch (ConfigurationException expected) {
assertContains(
expected.getMessage(),
"OptionalBindingTest$HasOptionalConstructor.<init>() "
+ "is annotated @Inject(optional=true), but constructors cannot be optional.");
}
}
static class HasOptionalConstructor {
// Suppress compiler errors by the error-prone checker InjectedConstructorAnnotations,
// which catches optional injected constructors.
@SuppressWarnings("InjectedConstructorAnnotations")
@Inject(optional = true)
HasOptionalConstructor() {}
}
@Inject(optional = true)
static A staticInjectA;
public void testStaticInjection() {
staticInjectA = injectA;
Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
requestStaticInjection(OptionalBindingTest.class);
}
});
assertSame(staticInjectA, injectA);
}
/**
* Test for bug 107, where we weren't doing optional injection properly for indirect injections.
*/
public void testIndirectOptionalInjection() {
Indirect indirect = Guice.createInjector().getInstance(Indirect.class);
assertNotNull(indirect.hasOptionalInjections);
indirect.hasOptionalInjections.assertNothingInjected();
}
static class Indirect {
@Inject HasOptionalInjections hasOptionalInjections;
}
interface A {}
interface B {}
interface C {}
interface D {}
interface E {}
interface F {}
interface G {}
}