Home | History | Annotate | Download | only in inject
      1 /*
      2  * Copyright (C) 2012 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 
     18 package com.google.inject;
     19 
     20 import junit.framework.TestCase;
     21 
     22 /**
     23  * Tests for {@link Binder#requireAtInjectOnConstructors()}
     24  *
     25  * @author sameb (at) google.com (Sam Berlin)
     26  */
     27 public class RequireAtInjectOnConstructorsTest extends TestCase {
     28 
     29   public void testNoCxtors_explicitBinding() {
     30     try {
     31       Guice.createInjector(new AbstractModule() {
     32         @Override
     33         protected void configure() {
     34           bind(NoCxtors.class);
     35           binder().requireAtInjectOnConstructors();
     36         }
     37       });
     38       fail();
     39     } catch (CreationException ce) {
     40       assertEquals(1, ce.getErrorMessages().size());
     41       Asserts.assertContains(ce.getMessage(),
     42           "1) Explicit @Inject annotations are required on constructors, but "
     43           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
     44           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
     45     }
     46   }
     47 
     48   public void testNoCxtors_jitBinding() {
     49     Injector injector = Guice.createInjector(new AbstractModule() {
     50       @Override
     51       protected void configure() {
     52         binder().requireAtInjectOnConstructors();
     53       }
     54     });
     55     try {
     56       injector.getInstance(NoCxtors.class);
     57       fail();
     58     } catch (ConfigurationException ce) {
     59       Asserts.assertContains(ce.getMessage(),
     60           "1) Explicit @Inject annotations are required on constructors, but "
     61           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
     62           "while locating " + NoCxtors.class.getName());
     63     }
     64   }
     65 
     66   public void testNoCxtors_implicitBinding() {
     67     try {
     68       Guice.createInjector(new AbstractModule() {
     69         @Override
     70         protected void configure() {
     71           bind(Interface.class).to(NoCxtors.class);
     72           binder().requireAtInjectOnConstructors();
     73         }
     74       });
     75       fail();
     76     } catch (CreationException ce) {
     77       assertEquals(1, ce.getErrorMessages().size());
     78       Asserts.assertContains(ce.getMessage(),
     79           "1) Explicit @Inject annotations are required on constructors, but "
     80           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
     81           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
     82     }
     83   }
     84 
     85   public void testNoCxtors_inheritedByPrivateModules() {
     86     try {
     87       Guice.createInjector(new AbstractModule() {
     88         @Override
     89         protected void configure() {
     90           binder().requireAtInjectOnConstructors();
     91           install(new PrivateModule() {
     92             @Override
     93             protected void configure() {
     94               bind(NoCxtors.class);
     95             }
     96           });
     97         }
     98       });
     99       fail();
    100     } catch (CreationException ce) {
    101       assertEquals(1, ce.getErrorMessages().size());
    102       Asserts.assertContains(ce.getMessage(),
    103           "1) Explicit @Inject annotations are required on constructors, but "
    104           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
    105           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
    106     }
    107   }
    108 
    109   public void testNoCxtors_accumulatesAllErrors() {
    110     try {
    111       Guice.createInjector(new AbstractModule() {
    112         @Override
    113         protected void configure() {
    114           bind(NoCxtors.class);
    115           bind(AnotherNoCxtors.class);
    116           binder().requireAtInjectOnConstructors();
    117         }
    118       });
    119       fail();
    120     } catch (CreationException ce) {
    121       assertEquals(2, ce.getErrorMessages().size());
    122       Asserts.assertContains(ce.getMessage(),
    123           "1) Explicit @Inject annotations are required on constructors, but "
    124           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
    125           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure",
    126           "2) Explicit @Inject annotations are required on constructors, but "
    127           + AnotherNoCxtors.class.getName() + " has no constructors annotated with @Inject",
    128           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
    129     }
    130   }
    131 
    132   public void testNoCxtors_separateOptionsForPrivateModules() {
    133     try {
    134       Guice.createInjector(new AbstractModule() {
    135         @Override
    136         protected void configure() {
    137           bind(AnotherNoCxtors.class);
    138           install(new PrivateModule() {
    139             @Override
    140             protected void configure() {
    141               binder().requireAtInjectOnConstructors();
    142               bind(NoCxtors.class);
    143             }
    144           });
    145         }
    146       });
    147       fail();
    148     } catch (CreationException ce) {
    149       // This is testing that the parent module doesn't fail because it isn't included
    150       // in the error message.
    151       assertEquals(1, ce.getErrorMessages().size());
    152       Asserts.assertContains(ce.getMessage(),
    153           "1) Explicit @Inject annotations are required on constructors, but "
    154           + NoCxtors.class.getName() + " has no constructors annotated with @Inject",
    155           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
    156     }
    157   }
    158 
    159   public void testManyConstructorsButNoneWithAtInject() {
    160     try {
    161       Guice.createInjector(new AbstractModule() {
    162         @Override
    163         protected void configure() {
    164           bind(ManyConstructors.class);
    165           binder().requireAtInjectOnConstructors();
    166         }
    167       });
    168       fail();
    169     } catch (CreationException ce) {
    170       assertEquals(1, ce.getErrorMessages().size());
    171       Asserts.assertContains(ce.getMessage(),
    172           "1) Explicit @Inject annotations are required on constructors, but "
    173           + ManyConstructors.class.getName() + " has no constructors annotated with @Inject",
    174           "at " + RequireAtInjectOnConstructorsTest.class.getName() + "$", "configure");
    175     }
    176   }
    177 
    178   public void testRequireAtInjectStillAllowsToConstructorBindings() {
    179     Injector injector = Guice.createInjector(new AbstractModule() {
    180         @Override
    181         protected void configure() {
    182           try {
    183             bind(ManyConstructors.class)
    184                 .toConstructor(ManyConstructors.class.getDeclaredConstructor());
    185           } catch (Exception e) {
    186             throw new RuntimeException(e);
    187           }
    188           binder().requireAtInjectOnConstructors();
    189         }
    190       });
    191     injector.getInstance(ManyConstructors.class);
    192   }
    193 
    194   private static interface Interface {}
    195   private static class NoCxtors implements Interface {}
    196   private static class AnotherNoCxtors {}
    197   private static class ManyConstructors {
    198     @SuppressWarnings("unused") ManyConstructors() {}
    199     @SuppressWarnings("unused") ManyConstructors(String a) {}
    200     @SuppressWarnings("unused") ManyConstructors(int a) {}
    201   }
    202 }
    203