/core/test/com/google/inject/ProvisionExceptionTest.java
Java | 470 lines | 375 code | 64 blank | 31 comment | 2 complexity | dd2e1b6c06266ed33de6027781662a97 MD5 | raw file
- /**
- * Copyright (C) 2007 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 static com.google.inject.Asserts.getDeclaringSourcePart;
- import static com.google.inject.Asserts.reserialize;
- import static java.lang.annotation.ElementType.CONSTRUCTOR;
- import static java.lang.annotation.ElementType.FIELD;
- import static java.lang.annotation.ElementType.METHOD;
- import static java.lang.annotation.ElementType.PARAMETER;
- import static java.lang.annotation.RetentionPolicy.RUNTIME;
- import com.google.common.base.Throwables;
- import com.google.inject.spi.Message;
- import junit.framework.TestCase;
- import java.io.IOException;
- import java.lang.annotation.Retention;
- import java.lang.annotation.Target;
- /**
- * @author jessewilson@google.com (Jesse Wilson)
- */
- @SuppressWarnings("UnusedDeclaration")
- public class ProvisionExceptionTest extends TestCase {
- public void testExceptionsCollapsed() {
- try {
- Guice.createInjector().getInstance(A.class);
- fail();
- } catch (ProvisionException e) {
- assertTrue(e.getCause() instanceof UnsupportedOperationException);
- assertContains(e.getMessage(), "Error injecting constructor",
- "for parameter 0 at com.google.inject.ProvisionExceptionTest$C.setD",
- "for field at com.google.inject.ProvisionExceptionTest$B.c",
- "for parameter 0 at com.google.inject.ProvisionExceptionTest$A");
- }
- }
- /**
- * There's a pass-through of user code in the scope. We want exceptions thrown by Guice to be
- * limited to a single exception, even if it passes through user code.
- */
- public void testExceptionsCollapsedWithScopes() {
- try {
- Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- bind(B.class).in(Scopes.SINGLETON);
- }
- }).getInstance(A.class);
- fail();
- } catch (ProvisionException e) {
- assertTrue(e.getCause() instanceof UnsupportedOperationException);
- assertFalse(e.getMessage().contains("custom provider"));
- assertContains(e.getMessage(), "Error injecting constructor",
- "for parameter 0 at com.google.inject.ProvisionExceptionTest$C.setD",
- "for field at com.google.inject.ProvisionExceptionTest$B.c",
- "for parameter 0 at com.google.inject.ProvisionExceptionTest$A");
- }
- }
- public void testMethodInjectionExceptions() {
- try {
- Guice.createInjector().getInstance(E.class);
- fail();
- } catch (ProvisionException e) {
- assertTrue(e.getCause() instanceof UnsupportedOperationException);
- assertContains(e.getMessage(), "Error injecting method",
- "at " + E.class.getName() + ".setObject(ProvisionExceptionTest.java:");
- }
- }
- public void testBindToProviderInstanceExceptions() {
- try {
- Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- bind(D.class).toProvider(new DProvider());
- }
- }).getInstance(D.class);
- fail();
- } catch (ProvisionException e) {
- assertTrue(e.getCause() instanceof UnsupportedOperationException);
- assertContains(e.getMessage(),
- "1) Error in custom provider, java.lang.UnsupportedOperationException",
- "at " + ProvisionExceptionTest.class.getName(),
- getDeclaringSourcePart(getClass()));
- }
- }
- /**
- * This test demonstrates that if the user throws a ProvisionException, we wrap it to add context.
- */
- public void testProvisionExceptionsAreWrappedForBindToType() {
- try {
- Guice.createInjector().getInstance(F.class);
- fail();
- } catch (ProvisionException e) {
- assertContains(e.getMessage(), "1) User Exception",
- "at " + F.class.getName() + ".<init>(ProvisionExceptionTest.java:");
- }
- }
- public void testProvisionExceptionsAreWrappedForBindToProviderType() {
- try {
- Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- bind(F.class).toProvider(FProvider.class);
- }
- }).getInstance(F.class);
- fail();
- } catch (ProvisionException e) {
- assertContains(e.getMessage(), "1) User Exception",
- "while locating ", FProvider.class.getName(),
- "while locating ", F.class.getName());
- }
- }
- public void testProvisionExceptionsAreWrappedForBindToProviderInstance() {
- try {
- Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- bind(F.class).toProvider(new FProvider());
- }
- }).getInstance(F.class);
- fail();
- } catch (ProvisionException e) {
- assertContains(e.getMessage(), "1) User Exception",
- "at " + ProvisionExceptionTest.class.getName(),
- getDeclaringSourcePart(getClass()));
- }
- }
- public void testProvisionExceptionIsSerializable() throws IOException {
- try {
- Guice.createInjector().getInstance(A.class);
- fail();
- } catch (ProvisionException expected) {
- ProvisionException reserialized = reserialize(expected);
- assertContains(reserialized.getMessage(),
- "1) Error injecting constructor, java.lang.UnsupportedOperationException",
- "at com.google.inject.ProvisionExceptionTest$RealD.<init>()",
- "at Key[type=com.google.inject.ProvisionExceptionTest$RealD, annotation=[none]]",
- "@com.google.inject.ProvisionExceptionTest$C.setD()[0]",
- "at Key[type=com.google.inject.ProvisionExceptionTest$C, annotation=[none]]",
- "@com.google.inject.ProvisionExceptionTest$B.c",
- "at Key[type=com.google.inject.ProvisionExceptionTest$B, annotation=[none]]",
- "@com.google.inject.ProvisionExceptionTest$A.<init>()[0]",
- "at Key[type=com.google.inject.ProvisionExceptionTest$A, annotation=[none]]");
- }
- }
- public void testMultipleCauses() {
- try {
- Guice.createInjector().getInstance(G.class);
- fail();
- } catch (ProvisionException e) {
- assertContains(e.getMessage(),
- "1) Error injecting method, java.lang.IllegalArgumentException",
- "Caused by: java.lang.IllegalArgumentException: java.lang.UnsupportedOperationException",
- "Caused by: java.lang.UnsupportedOperationException: Unsupported",
- "2) Error injecting method, java.lang.NullPointerException: can't inject second either",
- "Caused by: java.lang.NullPointerException: can't inject second either",
- "2 errors");
- }
- }
- public void testInjectInnerClass() throws Exception {
- Injector injector = Guice.createInjector();
- try {
- injector.getInstance(InnerClass.class);
- fail();
- } catch (Exception expected) {
- assertContains(expected.getMessage(),
- "Injecting into inner classes is not supported.",
- "while locating " + InnerClass.class.getName());
- }
- }
- public void testInjectLocalClass() throws Exception {
- class LocalClass {}
- Injector injector = Guice.createInjector();
- try {
- injector.getInstance(LocalClass.class);
- fail();
- } catch (Exception expected) {
- assertContains(expected.getMessage(),
- "Injecting into inner classes is not supported.",
- "while locating " + LocalClass.class.getName());
- }
- }
- public void testBindingAnnotationsOnMethodsAndConstructors() {
- try {
- Injector injector = Guice.createInjector();
- injector.getInstance(MethodWithBindingAnnotation.class);
- fail();
- } catch (ConfigurationException expected) {
- assertContains(expected.getMessage(), MethodWithBindingAnnotation.class.getName()
- + ".injectMe() is annotated with @", Green.class.getName() + "(), ",
- "but binding annotations should be applied to its parameters instead.",
- "while locating " + MethodWithBindingAnnotation.class.getName());
- }
- try {
- Guice.createInjector().getInstance(ConstructorWithBindingAnnotation.class);
- fail();
- } catch (ConfigurationException expected) {
- assertContains(expected.getMessage(), ConstructorWithBindingAnnotation.class.getName()
- + ".<init>() is annotated with @", Green.class.getName() + "(), ",
- "but binding annotations should be applied to its parameters instead.",
- "at " + ConstructorWithBindingAnnotation.class.getName() + ".class",
- "while locating " + ConstructorWithBindingAnnotation.class.getName());
- }
- }
- public void testBindingAnnotationWarningForScala() {
- Injector injector = Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- bind(String.class).annotatedWith(Green.class).toInstance("lime!");
- }
- });
- injector.getInstance(LikeScala.class);
- }
- public void testLinkedBindings() {
- Injector injector = Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- bind(D.class).to(RealD.class);
- }
- });
- try {
- injector.getInstance(D.class);
- fail();
- } catch (ProvisionException expected) {
- assertContains(expected.getMessage(),
- "at " + RealD.class.getName() + ".<init>(ProvisionExceptionTest.java:",
- "while locating " + RealD.class.getName(),
- "while locating " + D.class.getName());
- }
- }
- public void testProviderKeyBindings() {
- Injector injector = Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {
- bind(D.class).toProvider(DProvider.class);
- }
- });
- try {
- injector.getInstance(D.class);
- fail();
- } catch (ProvisionException expected) {
- assertContains(expected.getMessage(),
- "while locating " + DProvider.class.getName(),
- "while locating " + D.class.getName());
- }
- }
- public void testDuplicateCausesCollapsed() {
- final RuntimeException sharedException = new RuntimeException("fail");
- Injector injector = Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {}
- @Provides Integer i() { throw sharedException; }
- @Provides Double d() { throw sharedException; }
- });
- try{
- injector.getInstance(DoubleFailure.class);
- fail();
- } catch (ProvisionException pe) {
- assertEquals(sharedException, pe.getCause());
- assertEquals(2, pe.getErrorMessages().size());
- for (Message message : pe.getErrorMessages()) {
- assertEquals(sharedException, message.getCause());
- }
- }
- }
- public void testMultipleDuplicates() {
- final RuntimeException exception1 = new RuntimeException("fail");
- final RuntimeException exception2 = new RuntimeException("abort");
- Injector injector = Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {}
- @Provides Integer i() { throw exception1; }
- @Provides Double d() { throw exception1; }
- @Provides String s() { throw exception2; }
- @Provides Number n() { throw exception2; }
- });
- try{
- injector.getInstance(QuadrupleFailure.class);
- fail();
- } catch (ProvisionException pe) {
- assertNull(pe.getCause());
- assertEquals(4, pe.getErrorMessages().size());
- String e1 = Throwables.getStackTraceAsString(exception1);
- String e2 = Throwables.getStackTraceAsString(exception2);
- assertContains(pe.getMessage(),
- "\n1) ", e1, "\n2) ", "(same stack trace as error #1)",
- "\n3) ", e2, "\n4) ", "(same stack trace as error #3)");
- }
- }
- static class DoubleFailure {
- @Inject DoubleFailure(Integer i, Double d) { }
- }
- static class QuadrupleFailure {
- @Inject QuadrupleFailure(Integer i, Double d, String s, Number n) { }
- }
- public void testDuplicatesDifferentInstances() {
- Injector injector = Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {}
- @Provides Integer i() { throw new RuntimeException(); }
- });
- try{
- injector.getInstance(DoubleSameFailure.class);
- fail();
- } catch (ProvisionException pe) {
- assertNotNull(pe.toString(), pe.getCause());
- assertEquals(2, pe.getErrorMessages().size());
- for (Message message : pe.getErrorMessages()) {
- assertNotNull(message.toString(), message.getCause());
- }
- }
- }
- public void testMultipleDuplicatesDifferentInstaces() {
- Injector injector = Guice.createInjector(new AbstractModule() {
- @Override protected void configure() {}
- @Provides Integer i() { throw new RuntimeException("fail"); }
- @Provides String s() { throw new RuntimeException("abort"); }
- });
- try{
- injector.getInstance(QuadrupleSameFailure.class);
- fail();
- } catch (ProvisionException pe) {
- assertNull(pe.getCause());
- assertEquals(4, pe.getErrorMessages().size());
- assertContains(pe.getMessage(),
- "\n1) ", "Caused by: java.lang.RuntimeException: fail",
- "\n2) ", "Caused by: java.lang.RuntimeException (same stack trace as error #1)",
- "\n3) ", "Caused by: java.lang.RuntimeException: abort",
- "\n4) ", "Caused by: java.lang.RuntimeException (same stack trace as error #3)");
- }
- }
- static class DoubleSameFailure {
- @Inject DoubleSameFailure(Integer i1, Integer i2) { }
- }
- static class QuadrupleSameFailure {
- @Inject QuadrupleSameFailure(Integer i1, Integer i2, String s1, String s2) { }
- }
-
- private class InnerClass {}
- static class A {
- @Inject
- A(B b) { }
- }
- static class B {
- @Inject C c;
- }
- static class C {
- @Inject
- void setD(RealD d) { }
- }
- static class E {
- @Inject void setObject(Object o) {
- throw new UnsupportedOperationException();
- }
- }
- static class MethodWithBindingAnnotation {
- @Inject @Green void injectMe(String greenString) {}
- }
- static class ConstructorWithBindingAnnotation {
- // Suppress compiler errors by the error-prone checker InjectedConstructorAnnotations,
- // which catches injected constructors with binding annotations.
- @SuppressWarnings("InjectedConstructorAnnotations")
- @Inject @Green ConstructorWithBindingAnnotation(String greenString) {}
- }
- /**
- * In Scala, fields automatically get accessor methods with the same name. So we don't do
- * misplaced-binding annotation detection if the offending method has a matching field.
- */
- static class LikeScala {
- @Inject @Green String green;
- @Inject @Green String green() { return green; }
- }
- @Retention(RUNTIME)
- @Target({ FIELD, PARAMETER, CONSTRUCTOR, METHOD })
- @BindingAnnotation
- @interface Green {}
- interface D {}
- static class RealD implements D {
- @Inject RealD() {
- throw new UnsupportedOperationException();
- }
- }
- static class DProvider implements Provider<D> {
- public D get() {
- throw new UnsupportedOperationException();
- }
- }
- static class F {
- @Inject public F() {
- throw new ProvisionException("User Exception", new RuntimeException());
- }
- }
- static class FProvider implements Provider<F> {
- public F get() {
- return new F();
- }
- }
- static class G {
- @Inject void injectFirst() {
- throw new IllegalArgumentException(new UnsupportedOperationException("Unsupported"));
- }
- @Inject void injectSecond() {
- throw new NullPointerException("can't inject second either");
- }
- }
- }