1 /** 2 * Copyright (C) 2014 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.jdk8; 18 19 import com.google.inject.AbstractModule; 20 import com.google.inject.CreationException; 21 import com.google.inject.Guice; 22 import com.google.inject.Inject; 23 import com.google.inject.Injector; 24 import com.google.inject.Key; 25 import com.google.inject.Provider; 26 import com.google.inject.Provides; 27 import com.google.inject.ProvisionException; 28 import com.google.inject.TypeLiteral; 29 30 import junit.framework.TestCase; 31 32 import java.util.Collections; 33 import java.util.UUID; 34 import java.util.concurrent.Callable; 35 import java.util.concurrent.atomic.AtomicInteger; 36 import java.util.function.Predicate; 37 38 /** 39 * Test bindings to lambdas, method references, etc. 40 * 41 * @author cgdecker (at) google.com (Colin Decker) 42 */ 43 public class Java8LanguageFeatureBindingTest extends TestCase { 44 45 // Some of these tests are kind of weird. 46 // See https://github.com/google/guice/issues/757 for more on why they exist. 47 48 public void testBinding_lambdaToInterface() { 49 Injector injector = Guice.createInjector(new AbstractModule() { 50 @Override 51 protected void configure() { 52 bind(new TypeLiteral<Predicate<Object>>() {}).toInstance(o -> o != null); 53 } 54 }); 55 56 Predicate<Object> predicate = injector.getInstance(new Key<Predicate<Object>>() {}); 57 assertTrue(predicate.test(new Object())); 58 assertFalse(predicate.test(null)); 59 } 60 61 public void testProviderMethod_returningLambda() throws Exception { 62 Injector injector = Guice.createInjector(new AbstractModule() { 63 @Override 64 protected void configure() {} 65 66 @Provides 67 public Callable<String> provideCallable() { 68 return () -> "foo"; 69 } 70 }); 71 72 Callable<String> callable = injector.getInstance(new Key<Callable<String>>() {}); 73 assertEquals("foo", callable.call()); 74 } 75 76 public void testProviderMethod_containingLambda_throwingException() throws Exception { 77 Injector injector = Guice.createInjector(new AbstractModule() { 78 @Override 79 protected void configure() {} 80 81 @Provides 82 public Callable<String> provideCallable() { 83 if (Boolean.parseBoolean("false")) { // avoid dead code warnings 84 return () -> "foo"; 85 } else { 86 throw new RuntimeException("foo"); 87 } 88 } 89 }); 90 91 try { 92 injector.getInstance(new Key<Callable<String>>() {}); 93 } catch (ProvisionException expected) { 94 assertTrue(expected.getCause() instanceof RuntimeException); 95 assertEquals("foo", expected.getCause().getMessage()); 96 } 97 } 98 99 public void testProvider_usingJdk8Features() { 100 try { 101 Guice.createInjector(new AbstractModule() { 102 @Override 103 protected void configure() { 104 bind(String.class).toProvider(StringProvider.class); 105 } 106 }); 107 108 fail(); 109 } catch (CreationException expected) { 110 } 111 112 UUID uuid = UUID.randomUUID(); 113 Injector injector = Guice.createInjector(new AbstractModule() { 114 @Override 115 protected void configure() { 116 bind(UUID.class).toInstance(uuid); 117 bind(String.class).toProvider(StringProvider.class); 118 } 119 }); 120 121 assertEquals(uuid.toString(), injector.getInstance(String.class)); 122 } 123 124 private static final class StringProvider implements Provider<String> { 125 private final UUID uuid; 126 127 @Inject 128 StringProvider(UUID uuid) { 129 this.uuid = uuid; 130 } 131 132 @Override 133 public String get() { 134 return Collections.singleton(uuid).stream() 135 .map(UUID::toString) 136 .findFirst().get(); 137 } 138 } 139 140 public void testBinding_toProvider_lambda() { 141 Injector injector = Guice.createInjector(new AbstractModule() { 142 @Override 143 protected void configure() { 144 AtomicInteger i = new AtomicInteger(); 145 bind(String.class).toProvider(() -> "Hello" + i.incrementAndGet()); 146 } 147 }); 148 149 assertEquals("Hello1", injector.getInstance(String.class)); 150 assertEquals("Hello2", injector.getInstance(String.class)); 151 } 152 153 public void testBinding_toProvider_methodReference() { 154 Injector injector = Guice.createInjector(new AbstractModule() { 155 @Override 156 protected void configure() { 157 bind(String.class).toProvider(Java8LanguageFeatureBindingTest.this::provideString); 158 } 159 }); 160 161 Provider<String> provider = injector.getProvider(String.class); 162 assertEquals("Hello", provider.get()); 163 } 164 165 private String provideString() { 166 return "Hello"; 167 } 168 } 169