alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (OverrideModuleTest.java)

This example Java source code file (OverrideModuleTest.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

abstractmodule, annotation, atomicreference, hashequalstester, injector, key, module, newmodule, override, privatemodule, provider, scope, singleusescope, string, util

The OverrideModuleTest.java Java example source code

/**
 * Copyright (C) 2008 Google Inc.
 *
 * 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
 *
 * http://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 com.google.inject.util;

import static com.google.inject.Asserts.asModuleChain;
import static com.google.inject.Asserts.assertContains;
import static com.google.inject.Guice.createInjector;
import static com.google.inject.name.Names.named;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Binding;
import com.google.inject.CreationException;
import com.google.inject.Exposed;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.PrivateModule;
import com.google.inject.Provider;
import com.google.inject.Provides;
import com.google.inject.Scope;
import com.google.inject.ScopeAnnotation;
import com.google.inject.Stage;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.ModuleAnnotatedMethodScanner;

import junit.framework.TestCase;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author sberlin@gmail.com (Sam Berlin)
 */
public class OverrideModuleTest extends TestCase {

  private static final Key<String> key2 = Key.get(String.class, named("2"));
  private static final Key<String> key3 = Key.get(String.class, named("3"));

  private static final Module EMPTY_MODULE = new Module() {
    public void configure(Binder binder) {}
  };

  public void testOverride() {
    Injector injector = createInjector(Modules.override(newModule("A")).with(newModule("B")));
    assertEquals("B", injector.getInstance(String.class));
  }

  public void testOverrideMultiple() {
    Module module = Modules.override(newModule("A"), newModule(1), newModule(0.5f))
        .with(newModule("B"), newModule(2), newModule(1.5d));
    Injector injector = createInjector(module);
    assertEquals("B", injector.getInstance(String.class));
    assertEquals(2, injector.getInstance(Integer.class).intValue());
    assertEquals(0.5f, injector.getInstance(Float.class));
    assertEquals(1.5d, injector.getInstance(Double.class));
  }

  public void testOverrideUnmatchedTolerated() {
    Injector injector = createInjector(Modules.override(EMPTY_MODULE).with(newModule("B")));
    assertEquals("B", injector.getInstance(String.class));
  }

  public void testOverrideConstant() {
    Module original = new AbstractModule() {
      @Override protected void configure() {
        bindConstant().annotatedWith(named("Test")).to("A");
      }
    };

    Module replacements = new AbstractModule() {
      @Override protected void configure() {
        bindConstant().annotatedWith(named("Test")).to("B");
      }
    };

    Injector injector = createInjector(Modules.override(original).with(replacements));
    assertEquals("B", injector.getInstance(Key.get(String.class, named("Test"))));
  }

  public void testGetProviderInModule() {
    Module original = new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("A");
        bind(key2).toProvider(getProvider(String.class));
      }
    };

    Injector injector = createInjector(Modules.override(original).with(EMPTY_MODULE));
    assertEquals("A", injector.getInstance(String.class));
    assertEquals("A", injector.getInstance(key2));
  }

  public void testOverrideWhatGetProviderProvided() {
    Module original = new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("A");
        bind(key2).toProvider(getProvider(String.class));
      }
    };

    Module replacements = newModule("B");

    Injector injector = createInjector(Modules.override(original).with(replacements));
    assertEquals("B", injector.getInstance(String.class));
    assertEquals("B", injector.getInstance(key2));
  }

  public void testOverrideUsingOriginalsGetProvider() {
    Module original = new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("A");
        bind(key2).toInstance("B");
      }
    };

    Module replacements = new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toProvider(getProvider(key2));
      }
    };

    Injector injector = createInjector(Modules.override(original).with(replacements));
    assertEquals("B", injector.getInstance(String.class));
    assertEquals("B", injector.getInstance(key2));
  }

  public void testOverrideOfOverride() {
    Module original = new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("A1");
        bind(key2).toInstance("A2");
        bind(key3).toInstance("A3");
      }
    };

    Module replacements1 = new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("B1");
        bind(key2).toInstance("B2");
      }
    };

    Module overrides = Modules.override(original).with(replacements1);

    Module replacements2 = new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("C1");
        bind(key3).toInstance("C3");
      }
    };

    Injector injector = createInjector(Modules.override(overrides).with(replacements2));
    assertEquals("C1", injector.getInstance(String.class));
    assertEquals("B2", injector.getInstance(key2));
    assertEquals("C3", injector.getInstance(key3));
  }

  static class OuterReplacementsModule extends AbstractModule {
    @Override protected void configure() {
      install(new InnerReplacementsModule());
    }
  }
  static class InnerReplacementsModule extends AbstractModule {
    @Override protected void configure() {
      bind(String.class).toInstance("B");
      bind(String.class).toInstance("C");
    }
  }
  public void testOverridesTwiceFails() {
    Module original = newModule("A");
    Module replacements = new OuterReplacementsModule();
    Module module = Modules.override(original).with(replacements);
    try {
      createInjector(module);
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "A binding to java.lang.String was already configured at "
              + InnerReplacementsModule.class.getName(),
          asModuleChain(Modules.OverrideModule.class,
              OuterReplacementsModule.class, InnerReplacementsModule.class),
          "at " + InnerReplacementsModule.class.getName(),
          asModuleChain(Modules.OverrideModule.class,
              OuterReplacementsModule.class, InnerReplacementsModule.class));
    }
  }

  public void testOverridesDoesntFixTwiceBoundInOriginal() {
    Module original = new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("A");
        bind(String.class).toInstance("B");
      }
    };

    Module replacements = new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).toInstance("C");
      }
    };

    Module module = Modules.override(original).with(replacements);
    try {
      createInjector(module);
      fail();
    } catch (CreationException expected) {
      // The replacement comes first because we replace A with C,
      // then we encounter B and freak out.
      assertContains(expected.getMessage(),
          "1) A binding to java.lang.String was already configured at "
              + replacements.getClass().getName(),
          asModuleChain(Modules.OverrideModule.class, replacements.getClass()),
          "at " + original.getClass().getName(),
          asModuleChain(Modules.OverrideModule.class, original.getClass()));
    }
  }

  public void testStandardScopeAnnotation() {
    final SingleUseScope scope = new SingleUseScope();

    Module module = new AbstractModule() {
      @Override protected void configure() {
        bindScope(TestScopeAnnotation.class, scope);
        bind(String.class).in(TestScopeAnnotation.class);
      }
    };
    assertFalse(scope.used);

    Guice.createInjector(module);
    assertTrue(scope.used);
  }

  public void testOverrideUntargettedBinding() {
    Module original = new AbstractModule() {
      @Override protected void configure() {
        bind(Date.class);
      }
    };

    Module replacements = new AbstractModule() {
      @Override protected void configure() {
        bind(Date.class).toInstance(new Date(0));
      }
    };

    Injector injector = createInjector(Modules.override(original).with(replacements));
    assertEquals(0, injector.getInstance(Date.class).getTime());
  }

  public void testOverrideScopeAnnotation() {
    final Scope scope = new Scope() {
      public <T> Provider scope(Key key, Provider unscoped) {
        throw new AssertionError("Should not be called");
      }
    };

    final SingleUseScope replacementScope = new SingleUseScope();

    Module original = new AbstractModule() {
      @Override protected void configure() {
        bindScope(TestScopeAnnotation.class, scope);
        bind(Date.class).in(TestScopeAnnotation.class);
      }
    };

    Module replacements = new AbstractModule() {
      @Override protected void configure() {
        bindScope(TestScopeAnnotation.class, replacementScope);
      }
    };

    Injector injector = createInjector(Modules.override(original).with(replacements));
    injector.getInstance(Date.class);
    assertTrue(replacementScope.used);
  }

  public void testFailsIfOverridenScopeInstanceHasBeenUsed() {
    final Scope scope = new Scope() {
      public <T> Provider scope(Key key, Provider unscoped) {
        return unscoped;
      }

      @Override public String toString() {
        return "ORIGINAL SCOPE";
      }
    };

    final Module original = new AbstractModule() {
      @Override protected void configure() {
        bindScope(TestScopeAnnotation.class, scope);
        bind(Date.class).in(scope);
        bind(String.class).in(scope);
      }
    };
    Module originalWrapper = new AbstractModule() {
      @Override protected void configure() {
        install(original);
      }
    };

    Module replacements = new AbstractModule() {
      @Override protected void configure() {
        bindScope(TestScopeAnnotation.class, new SingleUseScope());
      }
    };

    try {
      createInjector(Modules.override(originalWrapper).with(replacements));
      fail("Exception expected");
    } catch (CreationException e) {
      assertContains(e.getMessage(),
          "1) The scope for @TestScopeAnnotation is bound directly and cannot be overridden.",
          "original binding at " + original.getClass().getName() + ".configure(",
          asModuleChain(originalWrapper.getClass(), original.getClass()),
          "bound directly at " + original.getClass().getName() + ".configure(",
          asModuleChain(originalWrapper.getClass(), original.getClass()),
          "bound directly at " + original.getClass().getName() + ".configure(",
          asModuleChain(originalWrapper.getClass(), original.getClass()),          
          "at ", replacements.getClass().getName() + ".configure(",
          asModuleChain(Modules.OverrideModule.class, replacements.getClass()));
    }
  }

  public void testOverrideIsLazy() {
    final AtomicReference<String> value = new AtomicReference("A");
    Module overridden = Modules.override(new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).annotatedWith(named("original")).toInstance(value.get());
      }
    }).with(new AbstractModule() {
      @Override protected void configure() {
        bind(String.class).annotatedWith(named("override")).toInstance(value.get());
      }
    });

    // the value.get() call should be deferred until Guice.createInjector
    value.set("B");
    Injector injector = Guice.createInjector(overridden);
    assertEquals("B", injector.getInstance(Key.get(String.class, named("original"))));
    assertEquals("B", injector.getInstance(Key.get(String.class, named("override"))));
  }

  public void testOverridePrivateModuleOverPrivateModule() {
    Module exposes5and6 = new AbstractModule() {
      @Override protected void configure() {
        install(new PrivateModule() {
          @Override protected void configure() {
            bind(Integer.class).toInstance(5);
            expose(Integer.class);

            bind(Character.class).toInstance('E');
          }
        });

        install(new PrivateModule() {
          @Override protected void configure() {
            bind(Long.class).toInstance(6L);
            expose(Long.class);

            bind(Character.class).toInstance('F');
          }
        });
      }
    };

    AbstractModule exposes15 = new AbstractModule() {
      @Override protected void configure() {
        install(new PrivateModule() {
          @Override protected void configure() {
            bind(Integer.class).toInstance(15);
            expose(Integer.class);

            bind(Character.class).toInstance('G');
          }
        });

        install(new PrivateModule() {
          @Override protected void configure() {
            bind(Character.class).toInstance('H');
          }
        });
      }
    };

    // override forwards
    Injector injector = Guice.createInjector(Modules.override(exposes5and6).with(exposes15));
    assertEquals(15, injector.getInstance(Integer.class).intValue());
    assertEquals(6L, injector.getInstance(Long.class).longValue());

    // and in reverse order
    Injector reverse = Guice.createInjector(Modules.override(exposes15).with(exposes5and6));
    assertEquals(5, reverse.getInstance(Integer.class).intValue());
    assertEquals(6L, reverse.getInstance(Long.class).longValue());
  }

  public void testOverrideModuleAndPrivateModule() {
    Module exposes5 = new PrivateModule() {
      @Override protected void configure() {
        bind(Integer.class).toInstance(5);
        expose(Integer.class);
      }
    };

    Module binds15 = new AbstractModule() {
      @Override protected void configure() {
        bind(Integer.class).toInstance(15);
      }
    };

    Injector injector = Guice.createInjector(Modules.override(exposes5).with(binds15));
    assertEquals(15, injector.getInstance(Integer.class).intValue());

    Injector reverse = Guice.createInjector(Modules.override(binds15).with(exposes5));
    assertEquals(5, reverse.getInstance(Integer.class).intValue());
  }

  public void testOverrideDeepExpose() {
    final AtomicReference<Provider charAProvider
        = new AtomicReference<Provider();

    Module exposes5 = new PrivateModule() {
      @Override protected void configure() {
        install(new PrivateModule() {
          @Override protected void configure() {
            bind(Integer.class).toInstance(5);
            expose(Integer.class);
            charAProvider.set(getProvider(Character.class));
            bind(Character.class).toInstance('A');
          }
        });
        expose(Integer.class);
      }
    };

    Injector injector = Guice.createInjector(Modules.override(exposes5).with(EMPTY_MODULE));
    assertEquals(5, injector.getInstance(Integer.class).intValue());
    assertEquals('A', charAProvider.getAndSet(null).get().charValue());

    injector = Guice.createInjector(Modules.override(EMPTY_MODULE).with(exposes5));
    assertEquals(5, injector.getInstance(Integer.class).intValue());
    assertEquals('A', charAProvider.getAndSet(null).get().charValue());

    final AtomicReference<Provider charBProvider
        = new AtomicReference<Provider();

    Module binds15 = new AbstractModule() {
      @Override protected void configure() {
        bind(Integer.class).toInstance(15);

        install(new PrivateModule() {
          @Override protected void configure() {
            charBProvider.set(getProvider(Character.class));
            bind(Character.class).toInstance('B');
          }
        });
      }
    };

    injector = Guice.createInjector(Modules.override(binds15).with(exposes5));
    assertEquals(5, injector.getInstance(Integer.class).intValue());
    assertEquals('A', charAProvider.getAndSet(null).get().charValue());
    assertEquals('B', charBProvider.getAndSet(null).get().charValue());

    injector = Guice.createInjector(Modules.override(exposes5).with(binds15));
    assertEquals(15, injector.getInstance(Integer.class).intValue());
    assertEquals('A', charAProvider.getAndSet(null).get().charValue());
    assertEquals('B', charBProvider.getAndSet(null).get().charValue());
  }

  @Retention(RUNTIME)
  @Target(TYPE)
  @ScopeAnnotation
  private static @interface TestScopeAnnotation {}

  private static class SingleUseScope implements Scope {
    boolean used = false;
    public <T> Provider scope(Key key, Provider unscoped) {
      assertFalse(used);
      used = true;
      return unscoped;
    }
  }
  
  static class NewModule<T> extends AbstractModule {
    private final T bound;
    NewModule(T bound) {
      this.bound = bound;
    }
    @Override protected void configure() {
      @SuppressWarnings("unchecked")
      Class<T> type = (Class)bound.getClass();
      bind(type).toInstance(bound);
    }
  }

  private static <T> Module newModule(final T bound) {
    return new NewModule<T>(bound);
  }
  
  private static final String RESULT = "RESULT";
  private static final String PRIVATE_INPUT = "PRIVATE_INPUT";
  private static final String OVERRIDDEN_INPUT = "FOO";
  private static final String OVERRIDDEN_RESULT = "Size: 3";
  private static final Key<String> RESULT_KEY = Key.get(String.class, named(RESULT));
  private static final Key<String> INPUT_KEY = Key.get(String.class, named(PRIVATE_INPUT));

  public void testExposedBindingOverride() throws Exception {
    Injector inj = Guice.createInjector(
        Modules.override(new ExampleModule()).with(
            new AbstractModule() {
              @Override protected void configure() {
                bind(RESULT_KEY).toInstance(OVERRIDDEN_RESULT);
              }
            }));
    assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT);
  }

  public void testPrivateBindingOverride() throws Exception {
    Injector inj = Guice.createInjector(
        Modules.override(new ExampleModule()).with(
            new AbstractModule() {
              @Override protected void configure() {
                bind(INPUT_KEY).toInstance(OVERRIDDEN_INPUT);
              }
            }));
    assertEquals(inj.getInstance(RESULT_KEY), OVERRIDDEN_RESULT);
  }

  public static class ExampleModule extends PrivateModule {
    @Provides @Exposed @Named(RESULT)
    public String provideResult(@Named(PRIVATE_INPUT) String input) {
      return "Size: " + input.length();
    }

    @Provides @Named(PRIVATE_INPUT)
    public String provideInput() {
      return "Hello World";
    }

    @Override protected void configure() {
    }
  }  
  
  public void testEqualsNotCalledByDefaultOnInstance() {
    final HashEqualsTester a = new HashEqualsTester();
    a.throwOnEquals = true;
    Guice.createInjector(Modules.override(new AbstractModule() {
      @Override
      protected void configure() {
       bind(String.class);
       bind(HashEqualsTester.class).toInstance(a);
      }
    }).with());
  }
  
  public void testEqualsNotCalledByDefaultOnProvider() {
    final HashEqualsTester a = new HashEqualsTester();
    a.throwOnEquals = true;
    Guice.createInjector(Modules.override(new AbstractModule() {
      @Override
      protected void configure() {
       bind(String.class);
       bind(Object.class).toProvider(a);
      }
    }).with());
  }
  
  public void testHashcodeNeverCalledOnInstance() {
    final HashEqualsTester a = new HashEqualsTester();
    a.throwOnHashcode = true;
    a.equality = "test";
    
    final HashEqualsTester b = new HashEqualsTester();
    b.throwOnHashcode = true;
    b.equality = "test";
    Guice.createInjector(Modules.override(new AbstractModule() {
      @Override
      protected void configure() {
       bind(String.class);
       bind(HashEqualsTester.class).toInstance(a);
       bind(HashEqualsTester.class).toInstance(b);
      }
    }).with());
  }
  
  public void testHashcodeNeverCalledOnProviderInstance() {
    final HashEqualsTester a = new HashEqualsTester();
    a.throwOnHashcode = true;
    a.equality = "test";
    
    final HashEqualsTester b = new HashEqualsTester();
    b.throwOnHashcode = true;
    b.equality = "test";
    Guice.createInjector(Modules.override(new AbstractModule() {
      @Override
      protected void configure() {
       bind(String.class);
       bind(Object.class).toProvider(a);
       bind(Object.class).toProvider(b);
      }
    }).with());
  }
  
  private static class HashEqualsTester implements Provider<Object> {
    private String equality;
    private boolean throwOnEquals;
    private boolean throwOnHashcode;
    
    @Override
    public boolean equals(Object obj) {
      if (throwOnEquals) {
        throw new RuntimeException();
      } else if (obj instanceof HashEqualsTester) {
        HashEqualsTester o = (HashEqualsTester)obj;
        if(o.throwOnEquals) {
          throw new RuntimeException();
        }
        if(equality == null && o.equality == null) {
          return this == o;
        } else {
          return Objects.equal(equality, o.equality);
        }
      } else {
        return false;
      }
    }
    
    @Override
    public int hashCode() {
      if(throwOnHashcode) {
        throw new RuntimeException();
      } else {
        return super.hashCode();
      }
    }
    
    public Object get() {
      return new Object();
    }
  }

  public void testCorrectStage() {
    final Stage stage = Stage.PRODUCTION;
    Module module = Modules.override(new AbstractModule() {
      @Override
      protected void configure() {
        if (currentStage() != Stage.PRODUCTION) {
          addError("Wronge stage in overridden module:" + currentStage());
        }
      }
    }).with(new AbstractModule() {
      @Override
      protected void configure() {
        if (currentStage() != Stage.PRODUCTION) {
          addError("Wronge stage in overriding module:" + currentStage());
        }
      }
    });
    Guice.createInjector(stage, module);
  }

  public void testOverridesApplyOriginalScanners() {
    Injector injector =
        Guice.createInjector(Modules.override(NamedMunger.module()).with(new AbstractModule() {
      @Override protected void configure() {}
      @TestProvides @Named("test") String provideString() { return "foo"; }
    }));

    assertNull(injector.getExistingBinding(Key.get(String.class, named("test"))));
    Binding<String> binding = injector.getBinding(Key.get(String.class, named("test-munged")));
    assertEquals("foo", binding.getProvider().get());
  }

  @Documented @Target(METHOD) @Retention(RUNTIME)
  private @interface TestProvides {}

  private static class NamedMunger extends ModuleAnnotatedMethodScanner {
    static Module module() {
      return new AbstractModule() {
        @Override protected void configure() {
          binder().scanModulesForAnnotatedMethods(new NamedMunger());
        }
      };
    }

    @Override
    public String toString() {
      return "NamedMunger";
    }

    @Override
    public Set<? extends Class annotationClasses() {
      return ImmutableSet.of(TestProvides.class);
    }

    @Override
    public <T> Key prepareMethod(Binder binder, Annotation annotation, Key key,
        InjectionPoint injectionPoint) {
      return Key.get(key.getTypeLiteral(),
          Names.named(((Named) key.getAnnotation()).value() + "-munged"));
    }
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java OverrideModuleTest.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.