1 /**
2  * Copyright (C) 2010 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.inject;
18 
19 import com.google.inject.internal.Errors;
20 import com.google.inject.name.Named;
21 import com.google.inject.name.Names;
22 
23 import junit.framework.TestCase;
24 
25 import java.io.IOException;
26 
27 /**
28  * Tests that ProvisionExceptions are readable and clearly indicate to the user what went wrong with
29  * their code.
30  *
31  * @author sameb@google.com (Sam Berlin)
32  */
33 public class ProvisionExceptionsTest extends TestCase {
34 
testConstructorRuntimeException()35   public void testConstructorRuntimeException() {
36     Injector injector = Guice.createInjector(new AbstractModule() {
37       @Override
38       protected void configure() {
39         bindConstant().annotatedWith(Names.named("runtime")).to(true);
40         bind(Exploder.class).to(Explosion.class);
41         bind(Tracer.class).to(TracerImpl.class);
42       }
43     });
44     try {
45       injector.getInstance(Tracer.class);
46       fail();
47     } catch(ProvisionException pe) {
48       // Make sure our initial error message gives the user exception.
49       Asserts.assertContains(pe.getMessage(),
50           "1) Error injecting constructor", "java.lang.IllegalStateException: boom!");
51       assertEquals(1, pe.getErrorMessages().size());
52       assertEquals(IllegalStateException.class, pe.getCause().getClass());
53       assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass());
54     }
55   }
56 
testConstructorCheckedException()57   public void testConstructorCheckedException() {
58     Injector injector = Guice.createInjector(new AbstractModule() {
59       @Override
60       protected void configure() {
61         bindConstant().annotatedWith(Names.named("runtime")).to(false);
62         bind(Exploder.class).to(Explosion.class);
63         bind(Tracer.class).to(TracerImpl.class);
64       }
65     });
66     try {
67       injector.getInstance(Tracer.class);
68       fail();
69     } catch(ProvisionException pe) {
70       // Make sure our initial error message gives the user exception.
71       Asserts.assertContains(pe.getMessage(),
72           "1) Error injecting constructor", "java.io.IOException: boom!");
73       assertEquals(1, pe.getErrorMessages().size());
74       assertEquals(IOException.class, pe.getCause().getClass());
75       assertEquals(IOException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass());
76     }
77   }
78 
testCustomProvidersRuntimeException()79   public void testCustomProvidersRuntimeException() {
80     Injector injector = Guice.createInjector(new AbstractModule() {
81       @Override
82       protected void configure() {
83         bind(Exploder.class).toProvider(new Provider<Exploder>() {
84           public Exploder get() {
85             return Explosion.createRuntime();
86           }
87         });
88         bind(Tracer.class).to(TracerImpl.class);
89       }
90     });
91     try {
92       injector.getInstance(Tracer.class);
93       fail();
94     } catch(ProvisionException pe) {
95       // Make sure our initial error message gives the user exception.
96       Asserts.assertContains(pe.getMessage(),
97           "1) Error in custom provider", "java.lang.IllegalStateException: boom!");
98       assertEquals(1, pe.getErrorMessages().size());
99       assertEquals(IllegalStateException.class, pe.getCause().getClass());
100       assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass());
101     }
102   }
103 
testProviderMethodRuntimeException()104   public void testProviderMethodRuntimeException() {
105     Injector injector = Guice.createInjector(new AbstractModule() {
106       @Override
107       protected void configure() {
108         bind(Tracer.class).to(TracerImpl.class);
109       }
110       @Provides Exploder exploder() {
111         return Explosion.createRuntime();
112       }
113     });
114     try {
115       injector.getInstance(Tracer.class);
116       fail();
117     } catch(ProvisionException pe) {
118       // Make sure our initial error message gives the user exception.
119       Asserts.assertContains(pe.getMessage(),
120           "1) Error in custom provider", "java.lang.IllegalStateException: boom!");
121       assertEquals(1, pe.getErrorMessages().size());
122       assertEquals(IllegalStateException.class, pe.getCause().getClass());
123       assertEquals(IllegalStateException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass());
124     }
125   }
126 
testProviderMethodCheckedException()127   public void testProviderMethodCheckedException() {
128     Injector injector = Guice.createInjector(new AbstractModule() {
129       @Override
130       protected void configure() {
131         bind(Tracer.class).to(TracerImpl.class);
132       }
133       @Provides Exploder exploder() throws IOException {
134         return Explosion.createChecked();
135       }
136     });
137     try {
138       injector.getInstance(Tracer.class);
139       fail();
140     } catch(ProvisionException pe) {
141       pe.printStackTrace();
142       // Make sure our initial error message gives the user exception.
143       Asserts.assertContains(pe.getMessage(),
144           "1) Error in custom provider", "java.io.IOException: boom!");
145       assertEquals(1, pe.getErrorMessages().size());
146       assertEquals(IOException.class, pe.getCause().getClass());
147       assertEquals(IOException.class, Errors.getOnlyCause(pe.getErrorMessages()).getClass());
148     }
149   }
150 
151   private static interface Exploder {}
152   public static class Explosion implements Exploder {
Explosion(@amed"runtime") boolean runtime)153     @Inject public Explosion(@Named("runtime") boolean runtime) throws IOException {
154       if(runtime) {
155         throw new IllegalStateException("boom!");
156       } else {
157         throw new IOException("boom!");
158       }
159     }
160 
createRuntime()161     public static Explosion createRuntime() {
162       try {
163         return new Explosion(true);
164       } catch(IOException iox) {
165         throw new RuntimeException();
166       }
167     }
168 
createChecked()169     public static Explosion createChecked() throws IOException {
170       return new Explosion(false);
171     }
172   }
173   private static interface Tracer {}
174   private static class TracerImpl implements Tracer {
TracerImpl(Exploder explosion)175     @Inject TracerImpl(Exploder explosion) {
176     }
177   }
178 }
179