mirror of
https://github.com/google/guice.git
synced 2024-04-21 12:32:36 +00:00
configure a presubmit to ensure that it stays formatted. Highlights include: * simplified import order * method annotations are now consistently defined on the preceding line * javadoc reformatted to 100 chars column width One test that contained line numbers in error messages had to be modified and the formatter didn't like some of the more complicated preprocessor directives (MOE and AOP). To avoid formatting the copyright notices as javadoc i did a preprocessing step to rewrite the initial '/**' to '/*' using perl ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=132718493
283 lines
8.2 KiB
Java
283 lines
8.2 KiB
Java
package com.google.inject;
|
|
|
|
import static com.google.inject.Asserts.assertContains;
|
|
import static com.google.inject.Asserts.getDeclaringSourcePart;
|
|
|
|
import com.google.common.base.Optional;
|
|
import com.google.inject.multibindings.OptionalBinder;
|
|
import com.google.inject.name.Named;
|
|
import com.google.inject.name.Names;
|
|
import com.google.inject.util.Providers;
|
|
import java.lang.annotation.Documented;
|
|
import java.lang.annotation.ElementType;
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.lang.annotation.Target;
|
|
import junit.framework.TestCase;
|
|
|
|
/** @author jessewilson@google.com (Jesse Wilson) */
|
|
public class NullableInjectionPointTest extends TestCase {
|
|
|
|
public void testInjectNullIntoNotNullableConstructor() {
|
|
try {
|
|
createInjector().getInstance(FooConstructor.class);
|
|
fail("Injecting null should fail with an error");
|
|
} catch (ProvisionException expected) {
|
|
assertContains(
|
|
expected.getMessage(),
|
|
"null returned by binding at " + getClass().getName(),
|
|
"the 1st parameter of " + FooConstructor.class.getName() + ".<init>(",
|
|
"is not @Nullable");
|
|
}
|
|
}
|
|
|
|
public void testInjectNullIntoNotNullableMethod() {
|
|
try {
|
|
createInjector().getInstance(FooMethod.class);
|
|
fail("Injecting null should fail with an error");
|
|
} catch (ProvisionException expected) {
|
|
assertContains(
|
|
expected.getMessage(),
|
|
"null returned by binding at " + getClass().getName(),
|
|
"the 1st parameter of " + FooMethod.class.getName() + ".setFoo(",
|
|
"is not @Nullable");
|
|
}
|
|
}
|
|
|
|
public void testInjectNullIntoNotNullableField() {
|
|
try {
|
|
createInjector().getInstance(FooField.class);
|
|
fail("Injecting null should fail with an error");
|
|
} catch (ProvisionException expected) {
|
|
assertContains(
|
|
expected.getMessage(),
|
|
"null returned by binding at " + getClass().getName(),
|
|
" but " + FooField.class.getName() + ".foo",
|
|
" is not @Nullable");
|
|
}
|
|
}
|
|
|
|
/** Provider.getInstance() is allowed to return null via direct calls to getInstance(). */
|
|
public void testGetInstanceOfNull() {
|
|
assertNull(createInjector().getInstance(Foo.class));
|
|
}
|
|
|
|
public void testInjectNullIntoNullableConstructor() {
|
|
NullableFooConstructor nfc = createInjector().getInstance(NullableFooConstructor.class);
|
|
assertNull(nfc.foo);
|
|
}
|
|
|
|
public void testInjectNullIntoNullableMethod() {
|
|
NullableFooMethod nfm = createInjector().getInstance(NullableFooMethod.class);
|
|
assertNull(nfm.foo);
|
|
}
|
|
|
|
public void testInjectNullIntoNullableField() {
|
|
NullableFooField nff = createInjector().getInstance(NullableFooField.class);
|
|
assertNull(nff.foo);
|
|
}
|
|
|
|
public void testInjectNullIntoCustomNullableConstructor() {
|
|
CustomNullableFooConstructor nfc =
|
|
createInjector().getInstance(CustomNullableFooConstructor.class);
|
|
assertNull(nfc.foo);
|
|
}
|
|
|
|
public void testInjectNullIntoCustomNullableMethod() {
|
|
CustomNullableFooMethod nfm = createInjector().getInstance(CustomNullableFooMethod.class);
|
|
assertNull(nfm.foo);
|
|
}
|
|
|
|
public void testInjectNullIntoCustomNullableField() {
|
|
CustomNullableFooField nff = createInjector().getInstance(CustomNullableFooField.class);
|
|
assertNull(nff.foo);
|
|
}
|
|
|
|
private Injector createInjector() {
|
|
return Guice.createInjector(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(Foo.class).toProvider(Providers.<Foo>of(null));
|
|
}
|
|
});
|
|
}
|
|
|
|
/** We haven't decided on what the desired behaviour of this test should be... */
|
|
public void testBindNullToInstance() {
|
|
try {
|
|
Guice.createInjector(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(Foo.class).toInstance(null);
|
|
}
|
|
});
|
|
fail();
|
|
} catch (CreationException expected) {
|
|
assertContains(
|
|
expected.getMessage(),
|
|
"Binding to null instances is not allowed.",
|
|
"at " + getClass().getName(),
|
|
getDeclaringSourcePart(getClass()));
|
|
}
|
|
}
|
|
|
|
public void testBindNullToProvider() {
|
|
Injector injector =
|
|
Guice.createInjector(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(Foo.class).toProvider(Providers.<Foo>of(null));
|
|
}
|
|
});
|
|
assertNull(injector.getInstance(NullableFooField.class).foo);
|
|
assertNull(injector.getInstance(CustomNullableFooField.class).foo);
|
|
|
|
try {
|
|
injector.getInstance(FooField.class);
|
|
fail("Expected ProvisionException");
|
|
} catch (ProvisionException expected) {
|
|
assertContains(expected.getMessage(), "null returned by binding at");
|
|
}
|
|
}
|
|
|
|
public void testBindScopedNull() {
|
|
Injector injector =
|
|
Guice.createInjector(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(Foo.class).toProvider(Providers.<Foo>of(null)).in(Scopes.SINGLETON);
|
|
}
|
|
});
|
|
assertNull(injector.getInstance(NullableFooField.class).foo);
|
|
assertNull(injector.getInstance(CustomNullableFooField.class).foo);
|
|
|
|
try {
|
|
injector.getInstance(FooField.class);
|
|
fail("Expected ProvisionException");
|
|
} catch (ProvisionException expected) {
|
|
assertContains(expected.getMessage(), "null returned by binding at");
|
|
}
|
|
}
|
|
|
|
public void testBindNullAsEagerSingleton() {
|
|
Injector injector =
|
|
Guice.createInjector(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(Foo.class).toProvider(Providers.<Foo>of(null)).asEagerSingleton();
|
|
}
|
|
});
|
|
assertNull(injector.getInstance(NullableFooField.class).foo);
|
|
assertNull(injector.getInstance(CustomNullableFooField.class).foo);
|
|
|
|
try {
|
|
injector.getInstance(FooField.class);
|
|
fail();
|
|
} catch (ProvisionException expected) {
|
|
assertContains(
|
|
expected.getMessage(),
|
|
"null returned by binding " + "at com.google.inject.NullableInjectionPointTest");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tests for a regression where dependency objects were not updated properly and OptionalBinder
|
|
* was rejecting nulls from its dependencies.
|
|
*/
|
|
public void testBindNullAndLinkFromOptionalBinder() {
|
|
Injector injector =
|
|
Guice.createInjector(
|
|
new AbstractModule() {
|
|
@Override
|
|
protected void configure() {
|
|
bind(Foo.class).toProvider(Providers.<Foo>of(null));
|
|
OptionalBinder.newOptionalBinder(binder(), Foo.class);
|
|
}
|
|
|
|
@Provides
|
|
@Named("throughProvidesMethod")
|
|
Foo provideFoo(Optional<Foo> foo) {
|
|
return foo.orNull();
|
|
}
|
|
});
|
|
assertNull(injector.getInstance(Key.get(Foo.class, Names.named("throughProvidesMethod"))));
|
|
}
|
|
|
|
static class Foo {}
|
|
|
|
static class FooConstructor {
|
|
@Inject
|
|
FooConstructor(Foo foo) {}
|
|
}
|
|
|
|
static class FooField {
|
|
@Inject Foo foo;
|
|
}
|
|
|
|
static class FooMethod {
|
|
@Inject
|
|
void setFoo(Foo foo) {}
|
|
}
|
|
|
|
static class NullableFooConstructor {
|
|
Foo foo;
|
|
|
|
@Inject
|
|
NullableFooConstructor(@Nullable Foo foo) {
|
|
this.foo = foo;
|
|
}
|
|
}
|
|
|
|
static class NullableFooField {
|
|
@Inject @Nullable Foo foo;
|
|
}
|
|
|
|
static class NullableFooMethod {
|
|
Foo foo;
|
|
|
|
@Inject
|
|
void setFoo(@Nullable Foo foo) {
|
|
this.foo = foo;
|
|
}
|
|
}
|
|
|
|
static class CustomNullableFooConstructor {
|
|
Foo foo;
|
|
|
|
@Inject
|
|
CustomNullableFooConstructor(@Namespace.Nullable Foo foo) {
|
|
this.foo = foo;
|
|
}
|
|
}
|
|
|
|
static class CustomNullableFooField {
|
|
@Inject @Namespace.Nullable Foo foo;
|
|
}
|
|
|
|
static class CustomNullableFooMethod {
|
|
Foo foo;
|
|
|
|
@Inject
|
|
void setFoo(@Namespace.Nullable Foo foo) {
|
|
this.foo = foo;
|
|
}
|
|
}
|
|
|
|
@Documented
|
|
@Retention(RetentionPolicy.RUNTIME)
|
|
@Target({ElementType.PARAMETER, ElementType.FIELD})
|
|
@interface Nullable {}
|
|
|
|
static interface Namespace {
|
|
@Documented
|
|
@Retention(RetentionPolicy.RUNTIME)
|
|
@Target({ElementType.PARAMETER, ElementType.FIELD})
|
|
@interface Nullable {}
|
|
}
|
|
}
|