package com.maxifier.guice.decorator; import com.google.inject.*; import org.testng.annotations.Test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; /** * Project: Maxifier * Date: 09.11.2009 * Time: 11:45:15 * <p/> * Copyright (c) 1999-2009 Magenta Corporation Ltd. All Rights Reserved. * Magenta Technology proprietary and confidential. * Use is subject to license terms. * * @author Aleksey Didik */ public class DecoratorTest { @Test public void testFullWrapper() { Module module = new AbstractModule() { @Override protected void configure() { bind(Service.class).to(GoogleService.class); new Decorator(binder()) .bind(HelloService.class) .to(WowDecorator.class) .decorate(ServiceDecorator.class) .decorate(HelloRealization.class); } }; Injector injector = Guice.createInjector(module); final HelloService helloService = injector.getInstance(HelloService.class); final String testResult = helloService.hello(); final String waited = HelloRealization.HELLO + GoogleService.NAME + WowDecorator.WOW; assertEquals(testResult, waited); } @Test public void testWithoutDecoration() { Module module = new AbstractModule() { @Override protected void configure() { new Decorator(binder()) .bind(HelloService.class) .to(HelloRealization.class); } }; Injector injector = Guice.createInjector(module); final HelloService helloService = injector.getInstance(HelloService.class); final String testResult = helloService.hello(); final String waited = HelloRealization.HELLO; assertEquals(testResult, waited); } @Test public void testEqualBindAndTo() { try { Guice.createInjector(Stage.TOOL, new AbstractModule() { @Override protected void configure() { new Decorator(binder()) .bind(HelloService.class) .to(HelloService.class); } }); fail("CreationException with DuplicateMemberException should be here"); } catch (CreationException e) { assertTrue(e.getCause() instanceof DuplicateMemberException); } } @Test public void testEqualToAndDecorated() { try { Guice.createInjector(Stage.TOOL, new AbstractModule() { @Override protected void configure() { new Decorator(binder()) .bind(HelloService.class) .to(HelloRealization.class) .decorate(ServiceDecorator.class) .decorate(HelloRealization.class); } }); fail("CreationException with DuplicateMemberException should be here"); } catch (CreationException e) { assertTrue(e.getCause() instanceof DuplicateMemberException); } } @Test public void testWithAnnotation() { Module module = new AbstractModule() { @Override protected void configure() { bind(Service.class).to(GoogleService.class); new Decorator(binder()) .bind(HelloService.class) .annotatedWith(TestAnnotation.class) .to(WowDecorator.class) .decorate(ServiceDecorator.class) .decorate(HelloRealization.class); } }; Injector inj = Guice.createInjector(module); final HelloService helloService = inj.getInstance(Key.get(HelloService.class, TestAnnotation.class)); final String testResult = helloService.hello(); final String waited = HelloRealization.HELLO + GoogleService.NAME + WowDecorator.WOW; assertEquals(testResult, waited); } @Test public void testDecorateInstance() { Module module = new AbstractModule() { @Override protected void configure() { bind(Service.class).to(GoogleService.class); new Decorator(binder()) .bind(HelloService.class) .annotatedWith(TestAnnotation.class) .to(WowDecorator.class) .decorate(ServiceDecorator.class) .decorate(new HelloRealization()); } }; Injector inj = Guice.createInjector(module); final HelloService helloService = inj.getInstance(Key.get(HelloService.class, TestAnnotation.class)); final String testResult = helloService.hello(); final String waited = HelloRealization.HELLO + GoogleService.NAME + WowDecorator.WOW; assertEquals(testResult, waited); } static boolean eagerFlag = false; @Test public void testEagerSingleton() { eagerFlag = false; Module module = new AbstractModule() { @Override protected void configure() { bind(Service.class).to(GoogleService.class); new Decorator(binder()) .bind(HelloService.class) .asEagerSingleton() .to(EagerService.class); } }; Guice.createInjector(module); assertTrue(eagerFlag); eagerFlag = false; } static class EagerService implements HelloService { EagerService() { DecoratorTest.eagerFlag = true; } @Override public String hello() { return "eager"; } } @Test public void testSingletonScope() { Module module = new AbstractModule() { @Override protected void configure() { bind(Service.class).to(GoogleService.class); new Decorator(binder()) .bind(HelloService.class) .in(Scopes.SINGLETON) .to(SingletonService.class); } }; Injector inj = Guice.createInjector(module); HelloService hs1 = inj.getInstance(HelloService.class); HelloService hs2 = inj.getInstance(HelloService.class); assertEquals(hs1, hs2); } static class SingletonService implements HelloService { @Override public String hello() { return "singleton"; } } interface Service { String serviceName(); } static class GoogleService implements Service { public static final String NAME = "Google"; public String serviceName() { return NAME; } } @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) @BindingAnnotation @interface TestAnnotation { } static class HelloRealization implements HelloService { public static final String HELLO = "Hello "; public String hello() { return HELLO; } } static interface HelloService { String hello(); } static class ServiceDecorator implements HelloService { private HelloService decorated; private final Service justService; @Inject public ServiceDecorator(@Decorated HelloService decorated, Service justService) { this.decorated = decorated; this.justService = justService; } public String hello() { return decorated.hello() + justService.serviceName(); } } static class WowDecorator implements HelloService { private HelloService decorated; public static final String WOW = "!"; @Inject public WowDecorator(@Decorated HelloService decorated) { this.decorated = decorated; } public String hello() { return decorated.hello() + WOW; } } }