1 /** 2 * Copyright (C) 2008 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.assistedinject; 18 19 import static com.google.inject.Asserts.assertContains; 20 import static com.google.inject.Asserts.assertEqualsBothWays; 21 22 import com.google.inject.AbstractModule; 23 import com.google.inject.ConfigurationException; 24 import com.google.inject.CreationException; 25 import com.google.inject.Guice; 26 import com.google.inject.Inject; 27 import com.google.inject.Injector; 28 import com.google.inject.Key; 29 import com.google.inject.Provider; 30 import com.google.inject.Stage; 31 import com.google.inject.TypeLiteral; 32 import com.google.inject.assistedinject.FactoryProvider2Test.Equals.ComparisonMethod; 33 import com.google.inject.assistedinject.FactoryProvider2Test.Equals.Impl; 34 import com.google.inject.matcher.Matchers; 35 import com.google.inject.name.Named; 36 import com.google.inject.name.Names; 37 38 import junit.framework.TestCase; 39 40 import java.util.Collection; 41 import java.util.Collections; 42 import java.util.Set; 43 import java.util.concurrent.atomic.AtomicInteger; 44 45 @SuppressWarnings("deprecation") 46 public class FactoryProvider2Test extends TestCase { 47 48 private enum Color { BLUE, GREEN, RED, GRAY, BLACK, ORANGE, PINK } 49 testAssistedFactory()50 public void testAssistedFactory() { 51 Injector injector = Guice.createInjector(new AbstractModule() { 52 @Override 53 protected void configure() { 54 bind(Double.class).toInstance(5.0d); 55 bind(ColoredCarFactory.class).toProvider( 56 FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 57 } 58 }); 59 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 60 61 Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE); 62 assertEquals(Color.BLUE, blueMustang.color); 63 assertEquals(5.0d, blueMustang.engineSize); 64 65 Mustang redMustang = (Mustang) carFactory.create(Color.RED); 66 assertEquals(Color.RED, redMustang.color); 67 assertEquals(5.0d, redMustang.engineSize); 68 } 69 testAssistedFactoryWithAnnotations()70 public void testAssistedFactoryWithAnnotations() { 71 Injector injector = Guice.createInjector(new AbstractModule() { 72 @Override 73 protected void configure() { 74 bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250); 75 bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984); 76 bind(ColoredCarFactory.class).toProvider( 77 FactoryProvider.newFactory(ColoredCarFactory.class, Camaro.class)); 78 } 79 }); 80 81 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 82 83 Camaro blueCamaro = (Camaro) carFactory.create(Color.BLUE); 84 assertEquals(Color.BLUE, blueCamaro.color); 85 assertEquals(1984, blueCamaro.modelYear); 86 assertEquals(250, blueCamaro.horsePower); 87 88 Camaro redCamaro = (Camaro) carFactory.create(Color.RED); 89 assertEquals(Color.RED, redCamaro.color); 90 assertEquals(1984, redCamaro.modelYear); 91 assertEquals(250, redCamaro.horsePower); 92 } 93 94 public interface Car {} 95 96 interface ColoredCarFactory { create(Color color)97 Car create(Color color); 98 } 99 100 public static class Mustang implements Car { 101 private final double engineSize; 102 private final Color color; 103 104 @Inject Mustang(double engineSize, @Assisted Color color)105 public Mustang(double engineSize, @Assisted Color color) { 106 this.engineSize = engineSize; 107 this.color = color; 108 } 109 drive()110 public void drive() {} 111 } 112 113 public static class Camaro implements Car { 114 private final int horsePower; 115 private final int modelYear; 116 private final Color color; 117 118 @Inject Camaro( @amed"horsePower") int horsePower, @Named("modelYear") int modelYear, @Assisted Color color)119 public Camaro( 120 @Named("horsePower") int horsePower, 121 @Named("modelYear") int modelYear, 122 @Assisted Color color) { 123 this.horsePower = horsePower; 124 this.modelYear = modelYear; 125 this.color = color; 126 } 127 } 128 129 interface SummerCarFactory { create(Color color, boolean convertable)130 Car create(Color color, boolean convertable); 131 } 132 testFactoryUsesInjectedConstructor()133 public void testFactoryUsesInjectedConstructor() { 134 Injector injector = Guice.createInjector(new AbstractModule() { 135 @Override 136 protected void configure() { 137 bind(float.class).toInstance(140f); 138 bind(SummerCarFactory.class).toProvider( 139 FactoryProvider.newFactory(SummerCarFactory.class, Corvette.class)); 140 } 141 }); 142 143 SummerCarFactory carFactory = injector.getInstance(SummerCarFactory.class); 144 145 Corvette redCorvette = (Corvette) carFactory.create(Color.RED, false); 146 assertEquals(Color.RED, redCorvette.color); 147 assertEquals(140f, redCorvette.maxMph); 148 assertFalse(redCorvette.isConvertable); 149 } 150 151 public static class Corvette implements Car { 152 private boolean isConvertable; 153 private Color color; 154 private float maxMph; 155 156 @SuppressWarnings("unused") Corvette(Color color, boolean isConvertable)157 public Corvette(Color color, boolean isConvertable) { 158 throw new IllegalStateException("Not an @AssistedInject constructor"); 159 } 160 161 @Inject Corvette(@ssisted Color color, Float maxMph, @Assisted boolean isConvertable)162 public Corvette(@Assisted Color color, Float maxMph, @Assisted boolean isConvertable) { 163 this.isConvertable = isConvertable; 164 this.color = color; 165 this.maxMph = maxMph; 166 } 167 } 168 testConstructorDoesntNeedAllFactoryMethodArguments()169 public void testConstructorDoesntNeedAllFactoryMethodArguments() { 170 Injector injector = Guice.createInjector(new AbstractModule() { 171 @Override 172 protected void configure() { 173 bind(SummerCarFactory.class).toProvider( 174 FactoryProvider.newFactory(SummerCarFactory.class, Beetle.class)); 175 } 176 }); 177 SummerCarFactory factory = injector.getInstance(SummerCarFactory.class); 178 179 Beetle beetle = (Beetle) factory.create(Color.RED, true); 180 assertSame(Color.RED, beetle.color); 181 } 182 183 public static class Beetle implements Car { 184 private final Color color; 185 @Inject Beetle(@ssisted Color color)186 public Beetle(@Assisted Color color) { 187 this.color = color; 188 } 189 } 190 testMethodsAndFieldsGetInjected()191 public void testMethodsAndFieldsGetInjected() { 192 Injector injector = Guice.createInjector(new AbstractModule() { 193 @Override 194 protected void configure() { 195 bind(String.class).toInstance("turbo"); 196 bind(int.class).toInstance(911); 197 bind(double.class).toInstance(50000d); 198 bind(ColoredCarFactory.class).toProvider( 199 FactoryProvider.newFactory(ColoredCarFactory.class, Porsche.class)); 200 } 201 }); 202 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 203 204 Porsche grayPorsche = (Porsche) carFactory.create(Color.GRAY); 205 assertEquals(Color.GRAY, grayPorsche.color); 206 assertEquals(50000d, grayPorsche.price); 207 assertEquals(911, grayPorsche.model); 208 assertEquals("turbo", grayPorsche.name); 209 } 210 211 public static class Porsche implements Car { 212 private final Color color; 213 private final double price; 214 private @Inject String name; 215 private int model; 216 217 @Inject Porsche(@ssisted Color color, double price)218 public Porsche(@Assisted Color color, double price) { 219 this.color = color; 220 this.price = price; 221 } 222 setModel(int model)223 @Inject void setModel(int model) { 224 this.model = model; 225 } 226 } 227 testProviderInjection()228 public void testProviderInjection() { 229 Injector injector = Guice.createInjector(new AbstractModule() { 230 @Override 231 protected void configure() { 232 bind(String.class).toInstance("trans am"); 233 bind(ColoredCarFactory.class).toProvider( 234 FactoryProvider.newFactory(ColoredCarFactory.class, Firebird.class)); 235 } 236 }); 237 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 238 239 Firebird blackFirebird = (Firebird) carFactory.create(Color.BLACK); 240 assertEquals(Color.BLACK, blackFirebird.color); 241 assertEquals("trans am", blackFirebird.modifiersProvider.get()); 242 } 243 244 public static class Firebird implements Car { 245 private final Provider<String> modifiersProvider; 246 private final Color color; 247 248 @Inject Firebird(Provider<String> modifiersProvider, @Assisted Color color)249 public Firebird(Provider<String> modifiersProvider, @Assisted Color color) { 250 this.modifiersProvider = modifiersProvider; 251 this.color = color; 252 } 253 } 254 testAssistedProviderInjection()255 public void testAssistedProviderInjection() { 256 Injector injector = Guice.createInjector(new AbstractModule() { 257 @Override 258 protected void configure() { 259 bind(String.class).toInstance("trans am"); 260 bind(ColoredCarFactory.class).toProvider( 261 FactoryProvider.newFactory(ColoredCarFactory.class, Flamingbird.class)); 262 } 263 }); 264 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 265 266 Flamingbird flamingbird = (Flamingbird) carFactory.create(Color.BLACK); 267 assertEquals(Color.BLACK, flamingbird.colorProvider.get()); 268 assertEquals("trans am", flamingbird.modifiersProvider.get()); 269 270 Flamingbird flamingbird2 = (Flamingbird) carFactory.create(Color.RED); 271 assertEquals(Color.RED, flamingbird2.colorProvider.get()); 272 assertEquals("trans am", flamingbird2.modifiersProvider.get()); 273 // Make sure the original flamingbird is black still. 274 assertEquals(Color.BLACK, flamingbird.colorProvider.get()); 275 } 276 277 public static class Flamingbird implements Car { 278 private final Provider<String> modifiersProvider; 279 private final Provider<Color> colorProvider; 280 281 @Inject Flamingbird(Provider<String> modifiersProvider, @Assisted Provider<Color> colorProvider)282 public Flamingbird(Provider<String> modifiersProvider, @Assisted Provider<Color> colorProvider) { 283 this.modifiersProvider = modifiersProvider; 284 this.colorProvider = colorProvider; 285 } 286 } 287 testTypeTokenInjection()288 public void testTypeTokenInjection() { 289 Injector injector = Guice.createInjector(new AbstractModule() { 290 @Override 291 protected void configure() { 292 bind(new TypeLiteral<Set<String>>() {}).toInstance(Collections.singleton("Flux Capacitor")); 293 bind(new TypeLiteral<Set<Integer>>() {}).toInstance(Collections.singleton(88)); 294 bind(ColoredCarFactory.class).toProvider( 295 FactoryProvider.newFactory(ColoredCarFactory.class, DeLorean.class)); 296 } 297 }); 298 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 299 300 DeLorean deLorean = (DeLorean) carFactory.create(Color.GRAY); 301 assertEquals(Color.GRAY, deLorean.color); 302 assertEquals("Flux Capacitor", deLorean.features.iterator().next()); 303 assertEquals(new Integer(88), deLorean.featureActivationSpeeds.iterator().next()); 304 } 305 306 public static class DeLorean implements Car { 307 private final Set<String> features; 308 private final Set<Integer> featureActivationSpeeds; 309 private final Color color; 310 311 @Inject DeLorean( Set<String> extraFeatures, Set<Integer> featureActivationSpeeds, @Assisted Color color)312 public DeLorean( 313 Set<String> extraFeatures, Set<Integer> featureActivationSpeeds, @Assisted Color color) { 314 this.features = extraFeatures; 315 this.featureActivationSpeeds = featureActivationSpeeds; 316 this.color = color; 317 } 318 } 319 testTypeTokenProviderInjection()320 public void testTypeTokenProviderInjection() { 321 Injector injector = Guice.createInjector(new AbstractModule() { 322 @Override 323 protected void configure() { 324 bind(new TypeLiteral<Set<String>>() { }).toInstance(Collections.singleton("Datsun")); 325 bind(ColoredCarFactory.class).toProvider( 326 FactoryProvider.newFactory(ColoredCarFactory.class, Z.class)); 327 } 328 }); 329 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 330 331 Z orangeZ = (Z) carFactory.create(Color.ORANGE); 332 assertEquals(Color.ORANGE, orangeZ.color); 333 assertEquals("Datsun", orangeZ.manufacturersProvider.get().iterator().next()); 334 } 335 336 public static class Z implements Car { 337 private final Provider<Set<String>> manufacturersProvider; 338 private final Color color; 339 340 @Inject Z(Provider<Set<String>> manufacturersProvider, @Assisted Color color)341 public Z(Provider<Set<String>> manufacturersProvider, @Assisted Color color) { 342 this.manufacturersProvider = manufacturersProvider; 343 this.color = color; 344 } 345 } 346 347 public static class Prius implements Car { 348 final Color color; 349 350 @Inject Prius(@ssisted Color color)351 private Prius(@Assisted Color color) { 352 this.color = color; 353 } 354 } 355 testAssistInjectionInNonPublicConstructor()356 public void testAssistInjectionInNonPublicConstructor() { 357 Injector injector = Guice.createInjector(new AbstractModule() { 358 @Override 359 protected void configure() { 360 bind(ColoredCarFactory.class).toProvider( 361 FactoryProvider.newFactory(ColoredCarFactory.class, Prius.class)); 362 } 363 }); 364 Prius prius = (Prius) injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE); 365 assertEquals(prius.color, Color.ORANGE); 366 } 367 368 public static class ExplodingCar implements Car { 369 @Inject ExplodingCar(@uppressWarnings"unused") @ssisted Color color)370 public ExplodingCar(@SuppressWarnings("unused") @Assisted Color color) { 371 throw new IllegalStateException("kaboom!"); 372 } 373 } 374 testExceptionDuringConstruction()375 public void testExceptionDuringConstruction() { 376 Injector injector = Guice.createInjector(new AbstractModule() { 377 @Override 378 protected void configure() { 379 bind(ColoredCarFactory.class).toProvider( 380 FactoryProvider.newFactory(ColoredCarFactory.class, ExplodingCar.class)); 381 } 382 }); 383 try { 384 injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE); 385 fail(); 386 } catch (IllegalStateException e) { 387 assertEquals("kaboom!", e.getMessage()); 388 } 389 } 390 391 public static class DefectiveCar implements Car { 392 @Inject DefectiveCar()393 public DefectiveCar() throws ExplosionException { 394 throw new ExplosionException(); 395 } 396 } 397 398 public static class ExplosionException extends Exception { } 399 public static class FireException extends Exception { } 400 401 public interface DefectiveCarFactoryWithNoExceptions { createCar()402 Car createCar(); 403 } 404 405 public interface DefectiveCarFactory { createCar()406 Car createCar() throws FireException; 407 } 408 409 public interface CorrectDefectiveCarFactory { createCar()410 Car createCar() throws FireException, ExplosionException; 411 } 412 testConstructorExceptionsAreThrownByFactory()413 public void testConstructorExceptionsAreThrownByFactory() { 414 Injector injector = Guice.createInjector(new AbstractModule() { 415 @Override 416 protected void configure() { 417 bind(CorrectDefectiveCarFactory.class).toProvider( 418 FactoryProvider.newFactory(CorrectDefectiveCarFactory.class, DefectiveCar.class)); 419 } 420 }); 421 try { 422 injector.getInstance(CorrectDefectiveCarFactory.class).createCar(); 423 fail(); 424 } catch (FireException e) { 425 fail(); 426 } catch (ExplosionException expected) { 427 } 428 } 429 430 public static class WildcardCollection { 431 432 public interface Factory { create(Collection<?> items)433 WildcardCollection create(Collection<?> items); 434 } 435 436 @Inject WildcardCollection(@uppressWarnings"unused") @ssisted Collection<?> items)437 public WildcardCollection(@SuppressWarnings("unused") @Assisted Collection<?> items) { } 438 } 439 testWildcardGenerics()440 public void testWildcardGenerics() { 441 Injector injector = Guice.createInjector(new AbstractModule() { 442 @Override 443 protected void configure() { 444 bind(WildcardCollection.Factory.class).toProvider( 445 FactoryProvider.newFactory(WildcardCollection.Factory.class, WildcardCollection.class)); 446 } 447 }); 448 WildcardCollection.Factory factory = injector.getInstance(WildcardCollection.Factory.class); 449 factory.create(Collections.emptyList()); 450 } 451 452 public static class SteeringWheel {} 453 454 public static class Fiat implements Car { 455 private final SteeringWheel steeringWheel; 456 private final Color color; 457 458 @Inject Fiat(SteeringWheel steeringWheel, @Assisted Color color)459 public Fiat(SteeringWheel steeringWheel, @Assisted Color color) { 460 this.steeringWheel = steeringWheel; 461 this.color = color; 462 } 463 } 464 testFactoryWithImplicitBindings()465 public void testFactoryWithImplicitBindings() { 466 Injector injector = Guice.createInjector(new AbstractModule() { 467 @Override 468 protected void configure() { 469 bind(ColoredCarFactory.class).toProvider( 470 FactoryProvider.newFactory(ColoredCarFactory.class, Fiat.class)); 471 } 472 }); 473 474 ColoredCarFactory coloredCarFactory = injector.getInstance(ColoredCarFactory.class); 475 Fiat fiat = (Fiat) coloredCarFactory.create(Color.GREEN); 476 assertEquals(Color.GREEN, fiat.color); 477 assertNotNull(fiat.steeringWheel); 478 } 479 testFactoryFailsWithMissingBinding()480 public void testFactoryFailsWithMissingBinding() { 481 try { 482 Guice.createInjector(new AbstractModule() { 483 @Override protected void configure() { 484 bind(ColoredCarFactory.class).toProvider( 485 FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 486 } 487 }); 488 fail(); 489 } catch (CreationException expected) { 490 assertContains(expected.getMessage(), 491 "Could not find a suitable constructor in java.lang.Double.", 492 "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java"); 493 } 494 } 495 testFactoryFailsWithMissingBindingInToolStage()496 public void testFactoryFailsWithMissingBindingInToolStage() { 497 try { 498 Guice.createInjector(Stage.TOOL, new AbstractModule() { 499 @Override protected void configure() { 500 bind(ColoredCarFactory.class).toProvider( 501 FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 502 } 503 }); 504 fail(); 505 } catch (CreationException expected) { 506 assertContains(expected.getMessage(), 507 "Could not find a suitable constructor in java.lang.Double.", 508 "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java"); 509 } 510 } 511 testMethodsDeclaredInObject()512 public void testMethodsDeclaredInObject() { 513 Injector injector = Guice.createInjector(new AbstractModule() { 514 @Override protected void configure() { 515 bind(Double.class).toInstance(5.0d); 516 bind(ColoredCarFactory.class).toProvider( 517 FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 518 } 519 }); 520 521 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 522 523 assertEqualsBothWays(carFactory, carFactory); 524 } 525 526 static class Subaru implements Car { 527 @Inject @Assisted Provider<Color> colorProvider; 528 } 529 testInjectingProviderOfParameter()530 public void testInjectingProviderOfParameter() { 531 Injector injector = Guice.createInjector(new AbstractModule() { 532 @Override protected void configure() { 533 bind(ColoredCarFactory.class).toProvider( 534 FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class)); 535 } 536 }); 537 538 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 539 Subaru subaru = (Subaru) carFactory.create(Color.RED); 540 541 assertSame(Color.RED, subaru.colorProvider.get()); 542 assertSame(Color.RED, subaru.colorProvider.get()); 543 544 Subaru sedan = (Subaru) carFactory.create(Color.BLUE); 545 assertSame(Color.BLUE, sedan.colorProvider.get()); 546 assertSame(Color.BLUE, sedan.colorProvider.get()); 547 548 // and make sure the subaru is still red 549 assertSame(Color.RED, subaru.colorProvider.get()); 550 } 551 testInjectingNullParameter()552 public void testInjectingNullParameter() { 553 Injector injector = Guice.createInjector(new AbstractModule() { 554 @Override protected void configure() { 555 bind(ColoredCarFactory.class).toProvider( 556 FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class)); 557 } 558 }); 559 560 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 561 Subaru subaru = (Subaru) carFactory.create(null); 562 563 assertNull(subaru.colorProvider.get()); 564 assertNull(subaru.colorProvider.get()); 565 } 566 567 interface ProviderBasedColoredCarFactory { createCar(Provider<Color> colorProvider, Provider<String> stringProvider)568 Car createCar(Provider<Color> colorProvider, Provider<String> stringProvider); createMustang(@ssisted"color") Provider<Color> colorProvider)569 Mustang createMustang(@Assisted("color") Provider<Color> colorProvider); 570 } 571 testAssistedProviderIsDisallowed()572 public void testAssistedProviderIsDisallowed() { 573 try { 574 Guice.createInjector(new AbstractModule() { 575 @Override protected void configure() { 576 bind(ProviderBasedColoredCarFactory.class).toProvider( 577 FactoryProvider.newFactory(ProviderBasedColoredCarFactory.class, Subaru.class)); 578 } 579 }); 580 fail(); 581 } catch (CreationException expected) { 582 assertEquals(expected.getMessage(), 4, expected.getErrorMessages().size()); 583 // Assert each method individually, because JDK7 doesn't guarantee method ordering. 584 assertContains(expected.getMessage(), 585 ") A Provider may not be a type in a factory method of an AssistedInject." 586 + "\n Offending instance is parameter [1] with key" 587 + " [com.google.inject.Provider<" + Color.class.getName() + ">] on method [" 588 + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]"); 589 assertContains(expected.getMessage(), 590 ") A Provider may not be a type in a factory method of an AssistedInject." 591 + "\n Offending instance is parameter [2] with key" 592 + " [com.google.inject.Provider<java.lang.String>] on method [" 593 + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]"); 594 assertContains(expected.getMessage(), 595 ") A Provider may not be a type in a factory method of an AssistedInject." 596 + "\n Offending instance is parameter [1] with key" 597 + " [com.google.inject.Provider<" + Color.class.getName() + ">" 598 + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]" 599 + " on method [" + ProviderBasedColoredCarFactory.class.getName() + ".createMustang()]" 600 ); 601 assertContains(expected.getMessage(), 602 ") No implementation for com.google.inject.assistedinject." 603 + "FactoryProvider2Test$ProviderBasedColoredCarFactory was bound."); 604 } 605 } 606 607 interface JavaxProviderBasedColoredCarFactory { createCar(javax.inject.Provider<Color> colorProvider, javax.inject.Provider<String> stringProvider)608 Car createCar(javax.inject.Provider<Color> colorProvider, javax.inject.Provider<String> stringProvider); createMustang(@ssisted"color") javax.inject.Provider<Color> colorProvider)609 Mustang createMustang(@Assisted("color") javax.inject.Provider<Color> colorProvider); 610 } 611 testAssistedJavaxProviderIsDisallowed()612 public void testAssistedJavaxProviderIsDisallowed() { 613 try { 614 Guice.createInjector(new AbstractModule() { 615 @Override protected void configure() { 616 bind(JavaxProviderBasedColoredCarFactory.class).toProvider( 617 FactoryProvider.newFactory(JavaxProviderBasedColoredCarFactory.class, Subaru.class)); 618 } 619 }); 620 fail(); 621 } catch (CreationException expected) { 622 assertEquals(expected.getMessage(), 4, expected.getErrorMessages().size()); 623 assertContains(expected.getMessage(), 624 ") A Provider may not be a type in a factory method of an AssistedInject." 625 + "\n Offending instance is parameter [1] with key" 626 + " [com.google.inject.Provider<" + Color.class.getName() + ">] on method [" 627 + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]"); 628 assertContains(expected.getMessage(), 629 ") A Provider may not be a type in a factory method of an AssistedInject." 630 + "\n Offending instance is parameter [2] with key" 631 + " [com.google.inject.Provider<java.lang.String>] on method [" 632 + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]"); 633 assertContains(expected.getMessage(), 634 ") A Provider may not be a type in a factory method of an AssistedInject." 635 + "\n Offending instance is parameter [1] with key" 636 + " [com.google.inject.Provider<" + Color.class.getName() + ">" 637 + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]" 638 + " on method [" + JavaxProviderBasedColoredCarFactory.class.getName() + ".createMustang()]" 639 ); 640 assertContains(expected.getMessage(), 641 ") No implementation for com.google.inject.assistedinject." 642 + "FactoryProvider2Test$JavaxProviderBasedColoredCarFactory was bound."); 643 } 644 } 645 testFactoryUseBeforeInitialization()646 public void testFactoryUseBeforeInitialization() { 647 ColoredCarFactory carFactory = FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class) 648 .get(); 649 try { 650 carFactory.create(Color.RED); 651 fail(); 652 } catch (IllegalStateException expected) { 653 assertContains(expected.getMessage(), 654 "Factories.create() factories cannot be used until they're initialized by Guice."); 655 } 656 } 657 658 interface MustangFactory { create(Color color)659 Mustang create(Color color); 660 } 661 testFactoryBuildingConcreteTypes()662 public void testFactoryBuildingConcreteTypes() { 663 Injector injector = Guice.createInjector(new AbstractModule() { 664 @Override 665 protected void configure() { 666 bind(double.class).toInstance(5.0d); 667 // note there is no 'thatMakes()' call here: 668 bind(MustangFactory.class).toProvider( 669 FactoryProvider.newFactory(MustangFactory.class, Mustang.class)); 670 } 671 }); 672 MustangFactory factory = injector.getInstance(MustangFactory.class); 673 674 Mustang mustang = factory.create(Color.RED); 675 assertSame(Color.RED, mustang.color); 676 assertEquals(5.0d, mustang.engineSize); 677 } 678 679 static class Fleet { 680 @Inject Mustang mustang; 681 @Inject Camaro camaro; 682 } 683 684 interface FleetFactory { createFleet(Color color)685 Fleet createFleet(Color color); 686 } 687 testInjectDeepIntoConstructedObjects()688 public void testInjectDeepIntoConstructedObjects() { 689 Injector injector = Guice.createInjector(new AbstractModule() { 690 @Override 691 protected void configure() { 692 bind(double.class).toInstance(5.0d); 693 bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250); 694 bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984); 695 bind(FleetFactory.class).toProvider(FactoryProvider.newFactory(FleetFactory.class, 696 Fleet.class)); 697 } 698 }); 699 700 FleetFactory fleetFactory = injector.getInstance(FleetFactory.class); 701 Fleet fleet = fleetFactory.createFleet(Color.RED); 702 703 assertSame(Color.RED, fleet.mustang.color); 704 assertEquals(5.0d, fleet.mustang.engineSize); 705 assertSame(Color.RED, fleet.camaro.color); 706 assertEquals(250, fleet.camaro.horsePower); 707 assertEquals(1984, fleet.camaro.modelYear); 708 } 709 710 interface TwoToneCarFactory { create(@ssisted"paint") Color paint, @Assisted("fabric") Color fabric)711 Car create(@Assisted("paint") Color paint, @Assisted("fabric") Color fabric); 712 } 713 714 static class Maxima implements Car { 715 @Inject @Assisted("paint") Color paint; 716 @Inject @Assisted("fabric") Color fabric; 717 } 718 testDistinctKeys()719 public void testDistinctKeys() { 720 Injector injector = Guice.createInjector(new AbstractModule() { 721 @Override 722 protected void configure() { 723 bind(TwoToneCarFactory.class).toProvider( 724 FactoryProvider.newFactory(TwoToneCarFactory.class, Maxima.class)); 725 } 726 }); 727 728 TwoToneCarFactory factory = injector.getInstance(TwoToneCarFactory.class); 729 Maxima maxima = (Maxima) factory.create(Color.BLACK, Color.GRAY); 730 assertSame(Color.BLACK, maxima.paint); 731 assertSame(Color.GRAY, maxima.fabric); 732 } 733 734 interface DoubleToneCarFactory { create(@ssisted"paint") Color paint, @Assisted("paint") Color morePaint)735 Car create(@Assisted("paint") Color paint, @Assisted("paint") Color morePaint); 736 } 737 testDuplicateKeys()738 public void testDuplicateKeys() { 739 try { 740 Guice.createInjector(new AbstractModule() { 741 @Override protected void configure() { 742 bind(DoubleToneCarFactory.class).toProvider( 743 FactoryProvider.newFactory(DoubleToneCarFactory.class, Maxima.class)); 744 } 745 }); 746 fail(); 747 } catch (CreationException expected) { 748 assertContains(expected.getMessage(), "A binding to " + Color.class.getName() + " annotated with @" 749 + Assisted.class.getName() + "(value=paint) was already configured at"); 750 } 751 } 752 753 /*if[AOP]*/ testMethodInterceptorsOnAssistedTypes()754 public void testMethodInterceptorsOnAssistedTypes() { 755 final AtomicInteger invocationCount = new AtomicInteger(); 756 final org.aopalliance.intercept.MethodInterceptor interceptor 757 = new org.aopalliance.intercept.MethodInterceptor() { 758 public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation) 759 throws Throwable { 760 invocationCount.incrementAndGet(); 761 return methodInvocation.proceed(); 762 } 763 }; 764 765 Injector injector = Guice.createInjector(new AbstractModule() { 766 @Override 767 protected void configure() { 768 bindInterceptor(Matchers.any(), Matchers.any(), interceptor); 769 bind(Double.class).toInstance(5.0d); 770 bind(ColoredCarFactory.class).toProvider( 771 FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 772 } 773 }); 774 775 ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class); 776 Mustang mustang = (Mustang) factory.create(Color.GREEN); 777 assertEquals(0, invocationCount.get()); 778 mustang.drive(); 779 assertEquals(1, invocationCount.get()); 780 } 781 /*end[AOP]*/ 782 783 /** 784 * Our factories aren't reusable across injectors. Although this behaviour isn't something we 785 * like, I have a test case to make sure the error message is pretty. 786 */ testFactoryReuseErrorMessageIsPretty()787 public void testFactoryReuseErrorMessageIsPretty() { 788 final Provider<ColoredCarFactory> factoryProvider 789 = FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class); 790 791 Guice.createInjector(new AbstractModule() { 792 @Override protected void configure() { 793 bind(Double.class).toInstance(5.0d); 794 bind(ColoredCarFactory.class).toProvider(factoryProvider); 795 } 796 }); 797 798 try { 799 Guice.createInjector(new AbstractModule() { 800 @Override protected void configure() { 801 bind(Double.class).toInstance(5.0d); 802 bind(ColoredCarFactory.class).toProvider(factoryProvider); 803 } 804 }); 805 fail(); 806 } catch(CreationException expected) { 807 assertContains(expected.getMessage(), 808 "Factories.create() factories may only be used in one Injector!"); 809 } 810 } 811 testNonAssistedFactoryMethodParameter()812 public void testNonAssistedFactoryMethodParameter() { 813 try { 814 FactoryProvider.newFactory(NamedParameterFactory.class, Mustang.class); 815 fail(); 816 } catch(ConfigurationException expected) { 817 assertContains(expected.getMessage(), 818 "Only @Assisted is allowed for factory parameters, but found @" + Named.class.getName()); 819 } 820 } 821 822 interface NamedParameterFactory { create(@amed"seats") int seats, double engineSize)823 Car create(@Named("seats") int seats, double engineSize); 824 } 825 826 testDefaultAssistedAnnotation()827 public void testDefaultAssistedAnnotation() throws NoSuchFieldException { 828 Assisted plainAssisted 829 = Subaru.class.getDeclaredField("colorProvider").getAnnotation(Assisted.class); 830 assertEqualsBothWays(FactoryProvider2.DEFAULT_ANNOTATION, plainAssisted); 831 assertEquals(FactoryProvider2.DEFAULT_ANNOTATION.toString(), plainAssisted.toString()); 832 } 833 834 interface GenericColoredCarFactory<T extends Car> { create(Color color)835 T create(Color color); 836 } 837 testGenericAssistedFactory()838 public void testGenericAssistedFactory() { 839 final TypeLiteral<GenericColoredCarFactory<Mustang>> mustangTypeLiteral 840 = new TypeLiteral<GenericColoredCarFactory<Mustang>>() {}; 841 final TypeLiteral<GenericColoredCarFactory<Camaro>> camaroTypeLiteral 842 = new TypeLiteral<GenericColoredCarFactory<Camaro>>() {}; 843 844 Injector injector = Guice.createInjector(new AbstractModule() { 845 @Override 846 protected void configure() { 847 bind(Double.class).toInstance(5.0d); 848 bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250); 849 bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984); 850 bind(mustangTypeLiteral) 851 .toProvider(FactoryProvider.newFactory(mustangTypeLiteral, TypeLiteral.get(Mustang.class))); 852 bind(camaroTypeLiteral) 853 .toProvider(FactoryProvider.newFactory(camaroTypeLiteral, TypeLiteral.get(Camaro.class))); 854 } 855 }); 856 857 GenericColoredCarFactory<Mustang> mustangFactory 858 = injector.getInstance(Key.get(mustangTypeLiteral)); 859 GenericColoredCarFactory<Camaro> camaroFactory 860 = injector.getInstance(Key.get(camaroTypeLiteral)); 861 862 Mustang blueMustang = mustangFactory.create(Color.BLUE); 863 assertEquals(Color.BLUE, blueMustang.color); 864 assertEquals(5.0d, blueMustang.engineSize); 865 866 Camaro redCamaro = camaroFactory.create(Color.RED); 867 assertEquals(Color.RED, redCamaro.color); 868 assertEquals(1984, redCamaro.modelYear); 869 assertEquals(250, redCamaro.horsePower); 870 } 871 872 @SuppressWarnings("unused") 873 public interface Insurance<T extends Car> { 874 } 875 876 public static class MustangInsurance implements Insurance<Mustang> { 877 private final double premium; 878 private final double limit; 879 @SuppressWarnings("unused") private Mustang car; 880 881 @Inject MustangInsurance(@amed"lowLimit") double limit, @Assisted Mustang car, @Assisted double premium)882 public MustangInsurance(@Named("lowLimit") double limit, @Assisted Mustang car, 883 @Assisted double premium) { 884 this.premium = premium; 885 this.limit = limit; 886 this.car = car; 887 } 888 sell()889 public void sell() {} 890 } 891 892 public static class CamaroInsurance implements Insurance<Camaro> { 893 private final double premium; 894 private final double limit; 895 @SuppressWarnings("unused") private Camaro car; 896 897 @Inject CamaroInsurance(@amed"highLimit") double limit, @Assisted Camaro car, @Assisted double premium)898 public CamaroInsurance(@Named("highLimit") double limit, @Assisted Camaro car, 899 @Assisted double premium) { 900 this.premium = premium; 901 this.limit = limit; 902 this.car = car; 903 } 904 sell()905 public void sell() {} 906 } 907 908 public interface MustangInsuranceFactory { create(Mustang car, double premium)909 public Insurance<Mustang> create(Mustang car, double premium); 910 } 911 912 public interface CamaroInsuranceFactory { create(Camaro car, double premium)913 public Insurance<Camaro> create(Camaro car, double premium); 914 } 915 testAssistedFactoryForConcreteType()916 public void testAssistedFactoryForConcreteType() { 917 918 Injector injector = Guice.createInjector(new AbstractModule() { 919 @Override 920 protected void configure() { 921 bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d); 922 bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d); 923 bind(MustangInsuranceFactory.class).toProvider( 924 FactoryProvider.newFactory(MustangInsuranceFactory.class, MustangInsurance.class)); 925 bind(CamaroInsuranceFactory.class).toProvider( 926 FactoryProvider.newFactory(CamaroInsuranceFactory.class, CamaroInsurance.class)); 927 } 928 }); 929 930 MustangInsuranceFactory mustangInsuranceFactory = 931 injector.getInstance(MustangInsuranceFactory.class); 932 CamaroInsuranceFactory camaroInsuranceFactory = 933 injector.getInstance(CamaroInsuranceFactory.class); 934 935 Mustang mustang = new Mustang(5000d, Color.BLACK); 936 MustangInsurance mustangPolicy = 937 (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d); 938 assertEquals(800.0d, mustangPolicy.premium); 939 assertEquals(50000.0d, mustangPolicy.limit); 940 941 Camaro camaro = new Camaro(3000, 1967, Color.BLUE); 942 CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d); 943 assertEquals(800.0d, camaroPolicy.premium); 944 assertEquals(100000.0d, camaroPolicy.limit); 945 } 946 947 public interface InsuranceFactory<T extends Car> { create(T car, double premium)948 public Insurance<T> create(T car, double premium); 949 } 950 testAssistedFactoryForParameterizedType()951 public void testAssistedFactoryForParameterizedType() { 952 final TypeLiteral<InsuranceFactory<Mustang>> mustangInsuranceFactoryType = 953 new TypeLiteral<InsuranceFactory<Mustang>>() {}; 954 final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType = 955 new TypeLiteral<InsuranceFactory<Camaro>>() {}; 956 957 Injector injector = Guice.createInjector(new AbstractModule() { 958 @Override 959 protected void configure() { 960 bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d); 961 bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d); 962 bind(mustangInsuranceFactoryType).toProvider(FactoryProvider.newFactory( 963 mustangInsuranceFactoryType, TypeLiteral.get(MustangInsurance.class))); 964 bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory( 965 camaroInsuranceFactoryType, TypeLiteral.get(CamaroInsurance.class))); 966 } 967 }); 968 969 InsuranceFactory<Mustang> mustangInsuranceFactory = 970 injector.getInstance(Key.get(mustangInsuranceFactoryType)); 971 InsuranceFactory<Camaro> camaroInsuranceFactory = 972 injector.getInstance(Key.get(camaroInsuranceFactoryType)); 973 974 Mustang mustang = new Mustang(5000d, Color.BLACK); 975 MustangInsurance mustangPolicy = 976 (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d); 977 assertEquals(800.0d, mustangPolicy.premium); 978 assertEquals(50000.0d, mustangPolicy.limit); 979 980 Camaro camaro = new Camaro(3000, 1967, Color.BLUE); 981 CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d); 982 assertEquals(800.0d, camaroPolicy.premium); 983 assertEquals(100000.0d, camaroPolicy.limit); 984 } 985 986 public static class AutoInsurance<T extends Car> implements Insurance<T> { 987 private final double premium; 988 private final double limit; 989 private final T car; 990 991 @Inject AutoInsurance(double limit, @Assisted T car, @Assisted double premium)992 public AutoInsurance(double limit, @Assisted T car, @Assisted double premium) { 993 this.limit = limit; 994 this.car = car; 995 this.premium = premium; 996 } 997 sell()998 public void sell() {} 999 } 1000 testAssistedFactoryForTypeVariableParameters()1001 public void testAssistedFactoryForTypeVariableParameters() { 1002 final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType = 1003 new TypeLiteral<InsuranceFactory<Camaro>>() {}; 1004 1005 Injector injector = Guice.createInjector(new AbstractModule() { 1006 @Override 1007 protected void configure() { 1008 bind(Double.class).toInstance(50000.0d); 1009 bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory( 1010 camaroInsuranceFactoryType, new TypeLiteral<AutoInsurance<Camaro>>() {})); 1011 } 1012 }); 1013 1014 InsuranceFactory<Camaro> camaroInsuranceFactory = 1015 injector.getInstance(Key.get(camaroInsuranceFactoryType)); 1016 1017 Camaro camaro = new Camaro(3000, 1967, Color.BLUE); 1018 AutoInsurance<?> camaroPolicy = 1019 (AutoInsurance<?>) camaroInsuranceFactory.create(camaro, 800.0d); 1020 assertEquals(800.0d, camaroPolicy.premium); 1021 assertEquals(50000.0d, camaroPolicy.limit); 1022 assertEquals(camaro, camaroPolicy.car); 1023 } 1024 testInjectingAndUsingInjector()1025 public void testInjectingAndUsingInjector() { 1026 Injector injector = Guice.createInjector(new AbstractModule() { 1027 @Override protected void configure() { 1028 bind(ColoredCarFactory.class).toProvider( 1029 FactoryProvider.newFactory(ColoredCarFactory.class, Segway.class)); 1030 } 1031 }); 1032 1033 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 1034 Segway green = (Segway)carFactory.create(Color.GREEN); 1035 assertSame(Color.GREEN, green.getColor()); 1036 assertSame(Color.GREEN, green.getColor()); 1037 1038 Segway pink = (Segway)carFactory.create(Color.PINK); 1039 assertSame(Color.PINK, pink.getColor()); 1040 assertSame(Color.PINK, pink.getColor()); 1041 assertSame(Color.GREEN, green.getColor()); 1042 } 1043 testDuplicateAssistedFactoryBinding()1044 public void testDuplicateAssistedFactoryBinding() { 1045 Injector injector = Guice.createInjector(new AbstractModule() { 1046 @Override 1047 protected void configure() { 1048 bind(Double.class).toInstance(5.0d); 1049 bind(ColoredCarFactory.class).toProvider( 1050 FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 1051 bind(ColoredCarFactory.class).toProvider( 1052 FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class)); 1053 } 1054 }); 1055 ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class); 1056 1057 Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE); 1058 assertEquals(Color.BLUE, blueMustang.color); 1059 assertEquals(5.0d, blueMustang.engineSize); 1060 1061 Mustang redMustang = (Mustang) carFactory.create(Color.RED); 1062 assertEquals(Color.RED, redMustang.color); 1063 assertEquals(5.0d, redMustang.engineSize); 1064 } 1065 1066 public interface Equals { 1067 1068 enum ComparisonMethod { SHALLOW, DEEP; } 1069 1070 interface Factory { equals(Equals.ComparisonMethod comparisonMethod)1071 Equals equals(Equals.ComparisonMethod comparisonMethod); 1072 } 1073 1074 public static class Impl implements Equals { 1075 private final double sigma; 1076 private final ComparisonMethod comparisonMethod; 1077 1078 @AssistedInject Impl(double sigma, @Assisted ComparisonMethod comparisonMethod)1079 public Impl(double sigma, @Assisted ComparisonMethod comparisonMethod) { 1080 this.sigma = sigma; 1081 this.comparisonMethod = comparisonMethod; 1082 } 1083 } 1084 } 1085 testFactoryMethodCalledEquals()1086 public void testFactoryMethodCalledEquals() { 1087 Injector injector = Guice.createInjector(new AbstractModule() { 1088 @Override 1089 protected void configure() { 1090 bind(Double.class).toInstance(0.01d); 1091 bind(Equals.Factory.class).toProvider( 1092 FactoryProvider.newFactory(Equals.Factory.class, Equals.Impl.class)); 1093 } 1094 }); 1095 Equals.Factory equalsFactory = injector.getInstance(Equals.Factory.class); 1096 Equals.Impl shallowEquals = (Impl) equalsFactory.equals(ComparisonMethod.SHALLOW); 1097 assertEquals(ComparisonMethod.SHALLOW, shallowEquals.comparisonMethod); 1098 assertEquals(0.01d, shallowEquals.sigma); 1099 } 1100 1101 static class Segway implements Car { 1102 @Inject Injector injector; 1103 getColor()1104 Color getColor() { return injector.getInstance(Key.get(Color.class, FactoryProvider2.DEFAULT_ANNOTATION)); } 1105 } 1106 testReturnValueMatchesParamValue()1107 public void testReturnValueMatchesParamValue() { 1108 Injector injector = Guice.createInjector(new AbstractModule() { 1109 @Override 1110 public void configure() { 1111 install(new FactoryModuleBuilder().build(Delegater.Factory.class)); 1112 } 1113 }); 1114 Delegater delegate = new Delegater(); 1115 Delegater user = injector.getInstance(Delegater.Factory.class).create(delegate); 1116 assertSame(delegate, user.delegate); 1117 } 1118 1119 static class Delegater { 1120 interface Factory { create(Delegater delegate)1121 Delegater create(Delegater delegate); 1122 } 1123 1124 private final Delegater delegate; 1125 Delegater(@ssisted Delegater delegater)1126 @Inject Delegater(@Assisted Delegater delegater) { 1127 this.delegate = delegater; 1128 } 1129 Delegater()1130 Delegater() { 1131 this.delegate = null; 1132 } 1133 } 1134 1135 public static abstract class AbstractAssisted { 1136 interface Factory<O extends AbstractAssisted, I extends CharSequence> { create(I string)1137 O create(I string); 1138 } 1139 } 1140 1141 static class ConcreteAssisted extends AbstractAssisted { ConcreteAssisted(@uppressWarnings"unused") @ssisted String string)1142 @Inject ConcreteAssisted(@SuppressWarnings("unused") @Assisted String string) {} 1143 } 1144 1145 static class ConcreteAssistedWithOverride extends AbstractAssisted { 1146 @AssistedInject ConcreteAssistedWithOverride(@uppressWarnings"unused") @ssisted String string)1147 ConcreteAssistedWithOverride(@SuppressWarnings("unused") @Assisted String string) {} 1148 1149 @AssistedInject ConcreteAssistedWithOverride(@uppressWarnings"unused") @ssisted StringBuilder sb)1150 ConcreteAssistedWithOverride(@SuppressWarnings("unused") @Assisted StringBuilder sb) {} 1151 1152 interface Factory extends AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> { create(String string)1153 @Override ConcreteAssistedWithOverride create(String string); 1154 } 1155 1156 interface Factory2 extends AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> { create(String string)1157 @Override ConcreteAssistedWithOverride create(String string); create(StringBuilder sb)1158 ConcreteAssistedWithOverride create(StringBuilder sb); 1159 } 1160 } 1161 1162 static class ConcreteAssistedWithoutOverride extends AbstractAssisted { ConcreteAssistedWithoutOverride(@uppressWarnings"unused") @ssisted String string)1163 @Inject ConcreteAssistedWithoutOverride(@SuppressWarnings("unused") @Assisted String string) {} 1164 interface Factory extends AbstractAssisted.Factory<ConcreteAssistedWithoutOverride, String> {} 1165 } 1166 1167 public static class Public extends AbstractAssisted { Public(@uppressWarnings"unused") @ssisted String string)1168 @AssistedInject Public(@SuppressWarnings("unused") @Assisted String string) {} Public(@uppressWarnings"unused") @ssisted StringBuilder sb)1169 @AssistedInject Public(@SuppressWarnings("unused") @Assisted StringBuilder sb) {} 1170 1171 public interface Factory extends AbstractAssisted.Factory<Public, String> { create(String string)1172 @Override Public create(String string); create(StringBuilder sb)1173 Public create(StringBuilder sb); 1174 } 1175 } 1176 1177 // See https://github.com/google/guice/issues/904 testGeneratedDefaultMethodsForwardCorrectly()1178 public void testGeneratedDefaultMethodsForwardCorrectly() { 1179 final Key<AbstractAssisted.Factory<ConcreteAssisted, String>> concreteKey = 1180 new Key<AbstractAssisted.Factory<ConcreteAssisted, String>>() {}; 1181 Injector injector = Guice.createInjector(new AbstractModule() { 1182 @Override protected void configure() { 1183 install(new FactoryModuleBuilder().build(ConcreteAssistedWithOverride.Factory.class)); 1184 install(new FactoryModuleBuilder().build(ConcreteAssistedWithOverride.Factory2.class)); 1185 install(new FactoryModuleBuilder().build(ConcreteAssistedWithoutOverride.Factory.class)); 1186 install(new FactoryModuleBuilder().build(Public.Factory.class)); 1187 install(new FactoryModuleBuilder().build(concreteKey)); 1188 } 1189 }); 1190 1191 ConcreteAssistedWithOverride.Factory factory1 = 1192 injector.getInstance(ConcreteAssistedWithOverride.Factory.class); 1193 factory1.create("foo"); 1194 AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> factory1Abstract = factory1; 1195 factory1Abstract.create("foo"); 1196 1197 ConcreteAssistedWithOverride.Factory2 factory2 = 1198 injector.getInstance(ConcreteAssistedWithOverride.Factory2.class); 1199 factory2.create("foo"); 1200 factory2.create(new StringBuilder("foo")); 1201 AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> factory2Abstract = factory2; 1202 factory2Abstract.create("foo"); 1203 1204 ConcreteAssistedWithoutOverride.Factory factory3 = 1205 injector.getInstance(ConcreteAssistedWithoutOverride.Factory.class); 1206 factory3.create("foo"); 1207 AbstractAssisted.Factory<ConcreteAssistedWithoutOverride, String> factory3Abstract = factory3; 1208 factory3Abstract.create("foo"); 1209 1210 Public.Factory factory4 = injector.getInstance(Public.Factory.class); 1211 factory4.create("foo"); 1212 factory4.create(new StringBuilder("foo")); 1213 AbstractAssisted.Factory<Public, String> factory4Abstract = factory4; 1214 factory4Abstract.create("foo"); 1215 1216 AbstractAssisted.Factory<ConcreteAssisted, String> factory5 = 1217 injector.getInstance(concreteKey); 1218 factory5.create("foo"); 1219 } 1220 } 1221