001    /**
002     Licensed to the Apache Software Foundation (ASF) under one or more
003     contributor license agreements.  See the NOTICE file distributed with
004     this work for additional information regarding copyright ownership.
005     The ASF licenses this file to You under the Apache License, Version 2.0
006     (the "License"); you may not use this file except in compliance with
007     the License.  You may obtain a copy of the License at
008    
009          http://www.apache.org/licenses/LICENSE-2.0
010    
011     Unless required by applicable law or agreed to in writing, software
012     distributed under the License is distributed on an "AS IS" BASIS,
013     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     See the License for the specific language governing permissions and
015     limitations under the License.
016    */
017    package org.apache.commons.inject.impl;
018    
019    import java.lang.annotation.Annotation;
020    import java.lang.reflect.Method;
021    import java.util.ArrayList;
022    import java.util.List;
023    import java.util.Map;
024    
025    import org.apache.commons.inject.api.CommonsInject;
026    import org.apache.commons.inject.api.IInjector;
027    import org.apache.commons.inject.api.IKey;
028    import org.apache.commons.inject.api.Key;
029    import org.apache.commons.inject.api.NoSuchBindingException;
030    import org.apache.commons.inject.api.bind.IBinder;
031    import org.apache.commons.inject.api.bind.IModule;
032    import org.apache.commons.inject.api.bind.Scopes;
033    import org.junit.Assert;
034    import org.junit.Test;
035    
036    public class SimpleInjectorTest {
037            private static final List<Object> FOO_LIST = new ArrayList<Object>();
038            private static final List<Object> BAR_LIST = new ArrayList<Object>();
039    
040            private IInjector newInjector() {
041                    final IModule module = new IModule(){
042                            @Override
043                            public void configure(IBinder pBinder) {
044                                    pBinder.bind(List.class).to(ArrayList.class).scope(Scopes.PER_CALL);
045                                    pBinder.bind(List.class, "foo").toInstance(FOO_LIST);
046                                    pBinder.bind(List.class, "bar").toInstance(BAR_LIST);
047                                    
048                            }
049                    };
050                    return CommonsInject.build(module);
051            }
052    
053            @Test
054            public void testSimpleInjector() throws Exception {
055                    final IInjector injector = newInjector();
056                    final List<?> fooList = injector.requireInstance(List.class, "foo");
057                    Assert.assertNotNull(fooList);
058                    Assert.assertSame(FOO_LIST, fooList);
059                    final List<?> barList = injector.requireInstance(List.class, "bar");
060                    Assert.assertNotNull(barList);
061                    Assert.assertSame(BAR_LIST, barList);
062                    final List<?> someList1 = injector.requireInstance(List.class);
063                    Assert.assertNotNull(someList1);
064                    Assert.assertNotSame(FOO_LIST, someList1);
065                    Assert.assertNotSame(BAR_LIST, someList1);
066                    final List<?> someList2 = injector.requireInstance(List.class);
067                    Assert.assertNotNull(someList2);
068                    Assert.assertNotSame(FOO_LIST, someList2);
069                    Assert.assertNotSame(BAR_LIST, someList2);
070                    Assert.assertNotSame(someList1, someList2);
071            }
072    
073            @Test
074            public void testAutomaticInjectorBinding() throws Exception {
075                    final IInjector injector1 = newInjector();
076                    final IInjector injector2 = injector1.requireInstance(IInjector.class);
077                    Assert.assertSame(injector1, injector2);
078            }
079    
080            @Test
081            public void testNoBinding() throws Exception {
082                    final IInjector injector = newInjector();
083                    {
084                            boolean haveException = false;
085                            try {
086                                    injector.requireInstance(Map.class);
087                                    Assert.fail("Expected exception");
088                            } catch (NoSuchBindingException e) {
089                                    Assert.assertEquals("No binding registered for key: Type=java.util.Map", e.getMessage());
090                                    haveException = true;
091                            }
092                            Assert.assertTrue(haveException);
093                    }
094                    {
095                            boolean haveException = false;
096                            try {
097                                    injector.requireInstance(List.class, "foobar");
098                                    Assert.fail("Expected exception");
099                            } catch (NoSuchBindingException e) {
100                                    Assert.assertEquals("No binding registered for key: Type=java.util.List, Name=foobar", e.getMessage());
101                                    haveException = true;
102                            }
103                            Assert.assertTrue(haveException);
104                    }
105                    {
106                            boolean haveException = false;
107                            try {
108                                    final Annotation[] annotations = new Annotation[]{getTestAnnotation()};
109                                    @SuppressWarnings("rawtypes")
110                                    final IKey<List> key = new Key<List>(List.class, "foo", annotations);
111                                    injector.requireInstance(key);
112                                    Assert.fail("Expected exception");
113                            } catch (NoSuchBindingException e) {
114                                    Assert.assertTrue(e.getMessage().startsWith("No binding registered for key: Type=java.util.List, Name=foo, Annotations=["));
115                                    haveException = true;
116                            }
117                            Assert.assertTrue(haveException);
118                    }
119            }
120            
121            private Annotation getTestAnnotation() throws Exception {
122                    final Class<?> cl = SimpleInjectorTest.class;
123                    final Method method = cl.getMethod("testScopes");
124                    return method.getAnnotation(Test.class);
125            }
126    
127            @Test
128            public void testScopes() throws Exception {
129                    final IModule module = new IModule(){
130                            @Override
131                            public void configure(IBinder pBinder) {
132                                    pBinder.bind(TimeRecordingObject.class, "eager").asEagerSingleton();
133                                    pBinder.bind(TimeRecordingObject.class, "lazy").asLazySingleton();
134                            }
135                    };
136                    long time0 = System.currentTimeMillis();
137                    final IInjector injector = CommonsInject.build(module);
138                    long time1 = System.currentTimeMillis();
139                    final TimeRecordingObject lazy0 = injector.getInstance(TimeRecordingObject.class, "lazy");
140                    final TimeRecordingObject lazy1 = injector.getInstance(TimeRecordingObject.class, "lazy");
141                    final TimeRecordingObject eager0 = injector.getInstance(TimeRecordingObject.class, "eager");
142                    final TimeRecordingObject eager1 = injector.getInstance(TimeRecordingObject.class, "eager");
143                    long time2 = System.currentTimeMillis();
144                    Assert.assertSame(eager0, eager1);
145                    Assert.assertSame(lazy0, lazy1);
146                    long eager0Time = eager0.getTimeOfCreation();
147                    long lazy0Time = lazy0.getTimeOfCreation();
148                    Assert.assertTrue(time0 <= eager0Time &&  eager0Time <= time1 &&  eager0Time <= time2);
149                    Assert.assertTrue(time0 <= lazy0Time &&  time1 <= lazy0Time &&  lazy0Time <= time2);
150            }
151    }