/* * Copyright 2019-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.guice; import com.google.inject.AbstractModule; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.FactoryBean; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.ResolvableType; import org.springframework.guice.annotation.EnableGuiceModules; import org.springframework.stereotype.Component; import static org.assertj.core.api.Assertions.assertThat; public class SuperClassTests { @Test public void testSpringInterface() { baseTestSpringInterface(ModulesConfig.class); } @Test public void testImportSpringInterface() { baseTestSpringInterface(ImportConfig.class); } @Test public void testComponentScanSpringInterface() { baseTestSpringInterface(ComponentScanConfig.class); } @SuppressWarnings("resource") private void baseTestSpringInterface(Class configClass) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass); assertThat(context.getBean(IParent.class) instanceof IGrandChildImpl).isTrue(); assertThat(context.getBean(IChild.class) instanceof IGrandChildImpl).isTrue(); assertThat(context.getBean(IGrandChild.class) instanceof IGrandChildImpl).isTrue(); } @Test public void testGuiceInterface() { baseTestGuiceInterface(ModulesConfig.class); } @Test public void testImportGuiceInterface() { baseTestGuiceInterface(ImportConfig.class); } @Test public void testComponentScanGuiceInterface() { baseTestGuiceInterface(ComponentScanConfig.class); } @SuppressWarnings("resource") private void baseTestGuiceInterface(Class configClass) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass); Injector injector = context.getBean(Injector.class); assertThat(injector.getInstance(IParent.class) instanceof IGrandChildImpl).isTrue(); assertThat(injector.getInstance(IChild.class) instanceof IGrandChildImpl).isTrue(); assertThat(injector.getInstance(IGrandChild.class) instanceof IGrandChildImpl).isTrue(); } @Test public void testSpringInterfaceWithType() { baseTestSpringInterfaceWithType(ModulesConfig.class); } @Test public void testImportSpringInterfaceWithType() { baseTestSpringInterfaceWithType(ImportConfig.class); } @Test public void testComponentScanSpringInterfaceWithType() { baseTestSpringInterfaceWithType(ComponentScanConfig.class); } @SuppressWarnings("resource") private void baseTestSpringInterfaceWithType(Class configClass) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass); String[] allParentBeanNames = context.getBeanNamesForType(IParentWithType.class); assertThat(allParentBeanNames.length).isEqualTo(2); String[] stringParentBeanNames = context .getBeanNamesForType(ResolvableType.forClassWithGenerics(IParentWithType.class, String.class)); assertThat(stringParentBeanNames.length).isEqualTo(1); assertThat(new TypeLiteral>() { }.getRawType().isInstance(context.getBean(stringParentBeanNames[0]))).isTrue(); String[] integerParentBeanNames = context .getBeanNamesForType(ResolvableType.forClassWithGenerics(IParentWithType.class, Integer.class)); assertThat(integerParentBeanNames.length).isEqualTo(1); assertThat(new TypeLiteral>() { }.getRawType().isInstance(context.getBean(integerParentBeanNames[0]))).isTrue(); String[] allChildBeanNames = context.getBeanNamesForType(IChildWithType.class); assertThat(allChildBeanNames.length).isEqualTo(2); String[] stringChildBeanNames = context .getBeanNamesForType(ResolvableType.forClassWithGenerics(IChildWithType.class, String.class)); assertThat(stringChildBeanNames.length).isEqualTo(1); assertThat(new TypeLiteral>() { }.getRawType().isInstance(context.getBean(stringChildBeanNames[0]))).isTrue(); String[] integerChildBeanNames = context .getBeanNamesForType(ResolvableType.forClassWithGenerics(IChildWithType.class, Integer.class)); assertThat(integerChildBeanNames.length).isEqualTo(1); assertThat(new TypeLiteral>() { }.getRawType().isInstance(context.getBean(integerChildBeanNames[0]))).isTrue(); String[] allGrandChildBeanNames = context.getBeanNamesForType(IGrandChildWithType.class); assertThat(allGrandChildBeanNames.length).isEqualTo(2); String[] stringGrandChildBeanNames = context .getBeanNamesForType(ResolvableType.forClassWithGenerics(IGrandChildWithType.class, String.class)); assertThat(stringGrandChildBeanNames.length).isEqualTo(1); assertThat(new TypeLiteral>() { }.getRawType().isInstance(context.getBean(stringGrandChildBeanNames[0]))).isTrue(); String[] integerGrandChildBeanNames = context .getBeanNamesForType(ResolvableType.forClassWithGenerics(IGrandChildWithType.class, Integer.class)); assertThat(integerGrandChildBeanNames.length).isEqualTo(1); assertThat(new TypeLiteral>() { }.getRawType().isInstance(context.getBean(integerGrandChildBeanNames[0]))).isTrue(); } @Test public void testGuiceInterfaceWithType() { baseTestGuiceInterfaceWithType(ModulesConfig.class); } @Test public void testImportGuiceInterfaceWithType() { baseTestGuiceInterfaceWithType(ImportConfig.class); } @Test public void testComponentScanGuiceInterfaceWithType() { baseTestGuiceInterfaceWithType(ComponentScanConfig.class); } @SuppressWarnings("resource") private void baseTestGuiceInterfaceWithType(Class configClass) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass); Injector injector = context.getBean(Injector.class); IParentWithType iParentString = injector .getInstance(Key.get(new TypeLiteral>() { })); assertThat(iParentString instanceof IGrandChildString).isTrue(); IParentWithType iParentInteger = injector .getInstance(Key.get(new TypeLiteral>() { })); assertThat(iParentInteger instanceof IGrandChildInteger).isTrue(); IChildWithType iChildString = injector.getInstance(Key.get(new TypeLiteral>() { })); assertThat(iChildString instanceof IGrandChildString).isTrue(); IChildWithType iChildInteger = injector .getInstance(Key.get(new TypeLiteral>() { })); assertThat(iChildInteger instanceof IGrandChildInteger).isTrue(); IGrandChildWithType iGrandChildString = injector .getInstance(Key.get(new TypeLiteral>() { })); assertThat(iGrandChildString instanceof IGrandChildString).isTrue(); IGrandChildWithType iGrandChildInteger = injector .getInstance(Key.get(new TypeLiteral>() { })); assertThat(iGrandChildInteger instanceof IGrandChildInteger).isTrue(); } @SuppressWarnings("resource") @Test public void testSpringClass() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ModulesConfig.class); IFoo iFoo = context.getBean(IFoo.class); assertThat(iFoo instanceof Foo).isTrue(); assertThat(iFoo instanceof SubFoo).isTrue(); Foo foo = context.getBean(Foo.class); assertThat(foo instanceof SubFoo).isTrue(); } @Test public void testGuiceClass() { baseTestGuiceClass(ModulesConfig.class); } @Test public void testImportGuiceClass() { baseTestGuiceClass(ImportConfig.class); } @Test public void testComponentScanGuiceClass() { baseTestGuiceClass(ComponentScanConfig.class); } @SuppressWarnings("resource") private void baseTestGuiceClass(Class configClass) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass); Injector injector = context.getBean(Injector.class); IFoo iFoo = injector.getInstance(IFoo.class); assertThat(iFoo instanceof Foo).isTrue(); assertThat(iFoo instanceof SubFoo).isTrue(); Foo foo = injector.getInstance(Foo.class); assertThat(foo instanceof SubFoo).isTrue(); } @Test public void testSpringClassWithType() { baseTestSpringClassWithType(ModulesConfig.class); } @Test public void testImportSpringClassWithType() { baseTestSpringClassWithType(ImportConfig.class); } @Test public void testComponentScanSpringClassWithType() { baseTestSpringClassWithType(ComponentScanConfig.class); } @SuppressWarnings("resource") private void baseTestSpringClassWithType(Class configClass) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass); String[] stringBeanNames = context .getBeanNamesForType(ResolvableType.forClassWithGenerics(IFooWithType.class, String.class)); assertThat(stringBeanNames.length).isEqualTo(1); assertThat(context.getBean(stringBeanNames[0]) instanceof StringFoo).isTrue(); assertThat(context.getBean(stringBeanNames[0]) instanceof SubStringFoo).isTrue(); stringBeanNames = context.getBeanNamesForType(StringFoo.class); assertThat(stringBeanNames.length).isEqualTo(1); assertThat(context.getBean(stringBeanNames[0]) instanceof StringFoo).isTrue(); assertThat(context.getBean(stringBeanNames[0]) instanceof SubStringFoo).isTrue(); String[] integerBeanNames = context .getBeanNamesForType(ResolvableType.forClassWithGenerics(IFooWithType.class, Integer.class)); assertThat(integerBeanNames.length).isEqualTo(1); assertThat(context.getBean(integerBeanNames[0]) instanceof IntegerFoo).isTrue(); assertThat(context.getBean(integerBeanNames[0]) instanceof SubIntegerFoo).isTrue(); integerBeanNames = context.getBeanNamesForType(IntegerFoo.class); assertThat(integerBeanNames.length).isEqualTo(1); assertThat(context.getBean(integerBeanNames[0]) instanceof IntegerFoo).isTrue(); assertThat(context.getBean(integerBeanNames[0]) instanceof SubIntegerFoo).isTrue(); } @Test public void testGuiceClassWithType() { baseTestGuiceClassWithType(ModulesConfig.class); } @Test public void testImportGuiceClassWithType() { baseTestGuiceClassWithType(ImportConfig.class); } @Test public void testComponentScanGuiceClassWithType() { baseTestGuiceClassWithType(ComponentScanConfig.class); } @SuppressWarnings("resource") private void baseTestGuiceClassWithType(Class configClass) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass); Injector injector = context.getBean(Injector.class); IFooWithType iFooWithTypeString = injector.getInstance(Key.get(new TypeLiteral>() { })); assertThat(iFooWithTypeString instanceof StringFoo).isTrue(); assertThat(iFooWithTypeString instanceof SubStringFoo).isTrue(); StringFoo stringFoo = injector.getInstance(StringFoo.class); assertThat(stringFoo instanceof SubStringFoo).isTrue(); IFooWithType iFooWithTypeInteger = injector .getInstance(Key.get(new TypeLiteral>() { })); assertThat(iFooWithTypeInteger instanceof IntegerFoo).isTrue(); assertThat(iFooWithTypeInteger instanceof SubIntegerFoo).isTrue(); IntegerFoo integerFoo = injector.getInstance(IntegerFoo.class); assertThat(integerFoo instanceof SubIntegerFoo).isTrue(); } @Test public void testSpringFactoryBean() { baseTestSpringFactoryBean(ModulesConfig.class); } @Test public void testImportSpringFactoryBean() { baseTestSpringFactoryBean(ImportConfig.class); } @Test public void testComponentScanSpringFactoryBean() { baseTestSpringFactoryBean(ComponentScanConfig.class); } private void baseTestSpringFactoryBean(Class configClass) { @SuppressWarnings("resource") AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass); Bar bar = context.getBean(Bar.class); assertThat(bar instanceof Bar).isTrue(); } @Test public void testGuiceFactoryBean() { baseTestGuiceFactoryBean(ModulesConfig.class); } @Test public void testImportGuiceFactoryBean() { baseTestGuiceFactoryBean(ImportConfig.class); } @Test public void testComponentScanGuiceFactoryBean() { baseTestGuiceFactoryBean(ComponentScanConfig.class); } private void baseTestGuiceFactoryBean(Class configClass) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configClass); Injector injector = context.getBean(Injector.class); Bar bar = injector.getInstance(Bar.class); assertThat(bar instanceof Bar).isTrue(); } static class DisableJITConfig { @Bean static AbstractModule disableJITModule() { return new AbstractModule() { @Override protected void configure() { binder().requireExplicitBindings(); } }; } } @Configuration @EnableGuiceModules static class ModulesConfig extends DisableJITConfig { @Bean IGrandChild iGrandChild() { return new IGrandChildImpl(); } @Bean IGrandChildWithType iChildString() { return new IGrandChildString(); } @Bean IGrandChildWithType iChildInteger() { return new IGrandChildInteger(); } @Bean SubFoo subFoo() { return new SubFoo(); } @Bean SubStringFoo stringFoo() { return new SubStringFoo(); } @Bean SubIntegerFoo integerFoo() { return new SubIntegerFoo(); } @Bean BarFactory barFactory() { return new BarFactory(); } } @Configuration @EnableGuiceModules @Import({ IGrandChildImpl.class, IGrandChildString.class, IGrandChildInteger.class, SubFoo.class, SubStringFoo.class, SubIntegerFoo.class, BarFactory.class }) static class ImportConfig extends DisableJITConfig { } @Configuration @EnableGuiceModules @ComponentScan(basePackageClasses = ComponentScanConfig.class, resourcePattern = "**/SuperClassTests**.class", excludeFilters = { @ComponentScan.Filter(Configuration.class) }) static class ComponentScanConfig extends DisableJITConfig { } public interface IParent { } public interface IChild extends IParent { } public interface IGrandChild extends IChild { } @Component public static class IGrandChildImpl implements IGrandChild { } public interface IParentWithType { } public interface IChildWithType extends IParentWithType { } public interface IGrandChildWithType extends IChildWithType { } @Component public static class IGrandChildString implements IGrandChildWithType { } @Component public static class IGrandChildInteger implements IGrandChildWithType { } public interface IFoo { } public static class Foo implements IFoo { } @Component public static class SubFoo extends Foo { } public interface IFooWithType { } public static class StringFoo implements IFooWithType { } @Component public static class SubStringFoo extends StringFoo { } public static class IntegerFoo implements IFooWithType { } @Component public static class SubIntegerFoo extends IntegerFoo { } public static class Bar { } @Component public static class BarFactory implements FactoryBean { @Override public Bar getObject() { return new Bar(); } @Override public Class getObjectType() { return Bar.class; } } }