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 }