package com.google.inject.throwingproviders; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assert_; import static org.junit.Assert.fail; import com.google.inject.TypeLiteral; import java.util.Arrays; import junit.framework.TestCase; /** * Unit tests for {@link CheckedProviders}. * * @author eatnumber1@google.com (Russ Harmon) */ public final class CheckedProvidersTest extends TestCase { private static interface StringCheckedProvider extends CheckedProvider<String> {} public void testCheckedProviderClass_get_returnsValidString() throws Exception { String expected = "rick"; StringCheckedProvider provider = CheckedProviders.of(StringCheckedProvider.class, expected); assertThat(provider.get()).isEqualTo(expected); } public void testCheckedProviderTypeLiteral_get_returnsValidString() throws Exception { String expected = "morty"; StringCheckedProvider provider = CheckedProviders.of(TypeLiteral.get(StringCheckedProvider.class), expected); assertThat(provider.get()).isEqualTo(expected); } public void testCheckedProviderClassNull_get_returnsNull() throws Exception { StringCheckedProvider provider = CheckedProviders.of(StringCheckedProvider.class, null); assertThat(provider.get()).isNull(); } public void testCheckedProviderTypeLiteralNull_get_returnsNull() throws Exception { StringCheckedProvider provider = CheckedProviders.of(TypeLiteral.get(StringCheckedProvider.class), null); assertThat(provider.get()).isNull(); } private static final class FooException extends Exception {} private interface FooCheckedProvider extends CheckedProvider<Object> { @Override Object get() throws FooException; } public void testThrowingCheckedProviderClass_get_throwsException() { FooCheckedProvider provider = CheckedProviders.throwing(FooCheckedProvider.class, FooException.class); try { provider.get(); fail(); } catch (FooException expected) { } } public void testThrowingCheckedProviderTypeLiteral_get_throwsException() { FooCheckedProvider provider = CheckedProviders.throwing(TypeLiteral.get(FooCheckedProvider.class), FooException.class); try { provider.get(); fail(); } catch (FooException expected) { } } private interface MoreMethodsCheckedProvider<T> extends CheckedProvider<T> { @Override T get() throws FooException; void otherMethod(); } public void testUnsupportedMethods_otherMethod_throwsIllegalArgumentException() throws NoSuchMethodException { String message = String.format( "%s may not declare any new methods, but declared %s", MoreMethodsCheckedProvider.class.getName(), Arrays.toString(MoreMethodsCheckedProvider.class.getDeclaredMethods())); try { CheckedProviders.of( new TypeLiteral<MoreMethodsCheckedProvider<String>>() {}, "SHOW ME WHAT YOU GOT"); fail("Expected an exception to be thrown"); } catch (IllegalArgumentException e) { assertThat(e).hasMessage(message); } } private static final class StringException extends RuntimeException { StringException(String arg) {} } public void testCheckThrowable_unsupportedThrowableConstructor_throwsIllegalArgumentException() { String message = String.format( "Thrown exception <%s> must have a no-argument constructor", StringException.class.getName()); try { CheckedProviders.throwing(FooCheckedProvider.class, StringException.class); fail("Expected an exception to be thrown"); } catch (IllegalArgumentException e) { assertThat(e).hasMessage(message); assert_() .withFailureMessage(String.format("exception <%s> with cause", e)) .that(e.getCause()) .isInstanceOf(NoSuchMethodException.class); } } private static final class BarException extends Exception {} public void testCheckThrowable_checkedExceptionNotDeclared_throwsIllegalArgumentException() throws Exception { String message = String.format( "Thrown exception <%s> is not declared to be thrown by <%s>", BarException.class.getName(), FooCheckedProvider.class.getMethod("get")); try { CheckedProviders.throwing(FooCheckedProvider.class, BarException.class); fail("Expected an exception to be thrown"); } catch (IllegalArgumentException e) { assertThat(e).hasMessage(message); } } private static final class ExpectedRuntimeException extends RuntimeException {} public void testCheckThrowable_runtimeExceptionNotDeclared_throwsExpectedRuntimeException() throws Exception { FooCheckedProvider provider = CheckedProviders.throwing(FooCheckedProvider.class, ExpectedRuntimeException.class); try { provider.get(); fail("Expected an exception to be thrown"); } catch (ExpectedRuntimeException e) { // expected } } private static final class ExpectedError extends Error {} public void testCheckThrowable_errorNotDeclared_throwsExpectedError() throws Exception { FooCheckedProvider provider = CheckedProviders.throwing(FooCheckedProvider.class, ExpectedError.class); try { provider.get(); fail("Expected an exception to be thrown"); } catch (ExpectedError e) { // expected } } }