Package com.google.inject

Source Code of com.google.inject.TypeConversionTest$DateHolder

/**
* Copyright (C) 2006 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;

import static com.google.inject.Asserts.assertContains;
import com.google.inject.internal.Iterables;
import com.google.inject.matcher.Matchers;
import com.google.inject.spi.TypeConverter;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.util.Date;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

/**
* @author crazybob@google.com (Bob Lee)
*/
public class TypeConversionTest extends TestCase {

  @Retention(RUNTIME)
  @BindingAnnotation @interface NumericValue {}

  @Retention(RUNTIME)
  @BindingAnnotation @interface BooleanValue {}

  @Retention(RUNTIME)
  @BindingAnnotation @interface EnumValue {}

  @Retention(RUNTIME)
  @BindingAnnotation @interface ClassName {}

  public static class Foo {
    @Inject @BooleanValue Boolean booleanField;
    @Inject @BooleanValue boolean primitiveBooleanField;
    @Inject @NumericValue Byte byteField;
    @Inject @NumericValue byte primitiveByteField;
    @Inject @NumericValue Short shortField;
    @Inject @NumericValue short primitiveShortField;
    @Inject @NumericValue Integer integerField;
    @Inject @NumericValue int primitiveIntField;
    @Inject @NumericValue Long longField;
    @Inject @NumericValue long primitiveLongField;
    @Inject @NumericValue Float floatField;
    @Inject @NumericValue float primitiveFloatField;
    @Inject @NumericValue Double doubleField;
    @Inject @NumericValue double primitiveDoubleField;
    @Inject @EnumValue Bar enumField;
    @Inject @ClassName Class<?> classField;
  }

  public enum Bar {
    TEE, BAZ, BOB
  }

  public void testOneConstantInjection() throws CreationException {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bindConstant().annotatedWith(NumericValue.class).to("5");
        bind(Simple.class);
      }
    });

    Simple simple = injector.getInstance(Simple.class);
    assertEquals(5, simple.i);
  }

  static class Simple {
    @Inject @NumericValue int i;
  }

  public void testConstantInjection() throws CreationException {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bindConstant().annotatedWith(NumericValue.class).to("5");
        bindConstant().annotatedWith(BooleanValue.class).to("true");
        bindConstant().annotatedWith(EnumValue.class).to("TEE");
        bindConstant().annotatedWith(ClassName.class).to(Foo.class.getName());
      }
    });

    Foo foo = injector.getInstance(Foo.class);

    checkNumbers(
      foo.integerField,
      foo.primitiveIntField,
      foo.longField,
      foo.primitiveLongField,
      foo.byteField,
      foo.primitiveByteField,
      foo.shortField,
      foo.primitiveShortField,
      foo.floatField,
      foo.primitiveFloatField,
      foo.doubleField,
      foo.primitiveDoubleField
    );

    assertEquals(Bar.TEE, foo.enumField);
    assertEquals(Foo.class, foo.classField);
  }

  void checkNumbers(Number... ns) {
    for (Number n : ns) {
      assertEquals(5, n.intValue());
    }
  }

  public void testInvalidInteger() throws CreationException {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bindConstant().annotatedWith(NumericValue.class).to("invalid");
      }
    });

    try {
      injector.getInstance(InvalidInteger.class);
      fail();
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(), "Error converting 'invalid'");
      assertContains(expected.getMessage(), "bound at " + getClass().getName());
      assertContains(expected.getMessage(), "to java.lang.Integer");
    }
  }

  public static class InvalidInteger {
    @Inject @NumericValue Integer integerField;
  }

  public void testInvalidCharacter() throws CreationException {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bindConstant().annotatedWith(NumericValue.class).to("invalid");
      }
    });

    try {
      injector.getInstance(InvalidCharacter.class);
      fail();
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(), "Error converting 'invalid'");
      assertContains(expected.getMessage(), "bound at " + getClass().getName());
      assertContains(expected.getMessage(), "to java.lang.Character");
    }
  }

  public static class InvalidCharacter {
    @Inject @NumericValue char foo;
  }

  public void testInvalidEnum() throws CreationException {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bindConstant().annotatedWith(NumericValue.class).to("invalid");
      }
    });

    try {
      injector.getInstance(InvalidEnum.class);
      fail();
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(), "Error converting 'invalid'");
      assertContains(expected.getMessage(), "bound at " + getClass().getName());
      assertContains(expected.getMessage(), "to " + Bar.class.getName());
    }
  }

  public static class InvalidEnum {
    @Inject @NumericValue Bar foo;
  }

  public void testToInstanceIsTreatedLikeConstant() throws CreationException {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(String.class).toInstance("5");
        bind(LongHolder.class);
      }
    });
   
    assertEquals(5L, (long) injector.getInstance(LongHolder.class).foo);
  }

  static class LongHolder {
    @Inject Long foo;
  }

  public void testCustomTypeConversion() throws CreationException {
    final Date result = new Date();

    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        convertToTypes(Matchers.only(TypeLiteral.get(Date.class)) , mockTypeConverter(result));
        bindConstant().annotatedWith(NumericValue.class).to("Today");
        bind(DateHolder.class);
      }
    });

    assertSame(result, injector.getInstance(DateHolder.class).date);
  }

  public void testInvalidCustomValue() throws CreationException {
    Module module = new AbstractModule() {
      protected void configure() {
        convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), failingTypeConverter());
        bindConstant().annotatedWith(NumericValue.class).to("invalid");
        bind(DateHolder.class);
      }
    };

    try {
      Guice.createInjector(module);
      fail();
    } catch (CreationException expected) {
      Throwable cause = Iterables.getOnlyElement(expected.getErrorMessages()).getCause();
      assertTrue(cause instanceof UnsupportedOperationException);
      assertContains(expected.getMessage(),
          "1) Error converting 'invalid' (bound at ", getClass().getName(),
          ".configure(TypeConversionTest.java:", "to java.util.Date",
          "using BrokenConverter which matches only(java.util.Date) ",
          "(bound at " + getClass().getName(), ".configure(TypeConversionTest.java:",
          "Reason: java.lang.UnsupportedOperationException: Cannot convert",
          "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:");
    }
  }

  public void testNullCustomValue() {
    Module module = new AbstractModule() {
      protected void configure() {
        convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(null));
        bindConstant().annotatedWith(NumericValue.class).to("foo");
        bind(DateHolder.class);
      }
    };

    try {
      Guice.createInjector(module);
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) Received null converting 'foo' (bound at ", getClass().getName(),
          ".configure(TypeConversionTest.java:", "to java.util.Date",
          "using CustomConverter which matches only(java.util.Date) ",
          "(bound at " + getClass().getName(), ".configure(TypeConversionTest.java:",
          "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:");
    }
  }

  public void testCustomValueTypeMismatch() {
    Module module = new AbstractModule() {
      protected void configure() {
        convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(-1));
        bindConstant().annotatedWith(NumericValue.class).to("foo");
        bind(DateHolder.class);
      }
    };

    try {
      Guice.createInjector(module);
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) Type mismatch converting 'foo' (bound at ", getClass().getName(),
          ".configure(TypeConversionTest.java:", "to java.util.Date",
          "using CustomConverter which matches only(java.util.Date) ",
          "(bound at " + getClass().getName(), ".configure(TypeConversionTest.java:",
          "Converter returned -1.",
          "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:");
    }
  }
 
  public void testStringIsConvertedOnlyOnce() {
    final TypeConverter converter = new TypeConverter() {
      boolean converted = false;
      public Object convert(String value, TypeLiteral<?> toType) {
        if (converted) {
          throw new AssertionFailedError("converted multiple times!");
        }
        converted = true;
        return new Date();
      }
    };

    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), converter);
        bindConstant().annotatedWith(NumericValue.class).to("unused");
      }
    });

    Date first = injector.getInstance(Key.get(Date.class, NumericValue.class));
    Date second = injector.getInstance(Key.get(Date.class, NumericValue.class));
    assertSame(first, second);
  }

  public void testAmbiguousTypeConversion() {
    Module module = new AbstractModule() {
      protected void configure() {
        convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(new Date()));
        convertToTypes(Matchers.only(TypeLiteral.get(Date.class)), mockTypeConverter(new Date()));
        bindConstant().annotatedWith(NumericValue.class).to("foo");
        bind(DateHolder.class);
      }
    };

    try {
      Guice.createInjector(module);
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) Multiple converters can convert 'foo' (bound at ", getClass().getName(),
          ".configure(TypeConversionTest.java:", "to java.util.Date:",
          "CustomConverter which matches only(java.util.Date)", "and",
          "CustomConverter which matches only(java.util.Date)",
          "Please adjust your type converter configuration to avoid overlapping matches.",
          "at " + DateHolder.class.getName() + ".date(TypeConversionTest.java:");
    }
  }

  TypeConverter mockTypeConverter(final Object result) {
    return new TypeConverter() {
      public Object convert(String value, TypeLiteral<?> toType) {
        return result;
      }

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

  private TypeConverter failingTypeConverter() {
    return new TypeConverter() {
      public Object convert(String value, TypeLiteral<?> toType) {
        throw new UnsupportedOperationException("Cannot convert");
      }
      @Override public String toString() {
        return "BrokenConverter";
      }
    };
  }

  static class DateHolder {
    @Inject @NumericValue Date date;
  }

  public void testCannotConvertUnannotatedBindings() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(String.class).toInstance("55");
      }
    });

    try {
      injector.getInstance(Integer.class);
      fail("Converted an unannotated String to an Integer");
    } catch (ConfigurationException expected) {
      Asserts.assertContains(expected.getMessage(),
          "Could not find a suitable constructor in java.lang.Integer.");
    }
  }
}
TOP

Related Classes of com.google.inject.TypeConversionTest$DateHolder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.