/** * Copyright (c) 2014 - 2017 Frank Appel * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Frank Appel - initial API and implementation */ package com.codeaffine.util.inject; import static com.codeaffine.test.util.lang.ThrowableCaptor.thrownBy; import static com.codeaffine.util.inject.Context.ABSTRACT_TYPE_CANNOT_BE_INSTANTIATED; import static com.codeaffine.util.inject.Context.INTERFACE_CANNOT_BE_INSTANTIATED; import static com.codeaffine.util.inject.Context.WRONG_CONSTRUCTOR_COUNT; import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import org.junit.Before; import org.junit.Test; import com.codeaffine.util.Disposable; public class ContextTest { private Context context; static class Pojo { final Runnable injected; Pojo( Runnable injected ) { this.injected = injected; } } static class TooManyConstructorPojo extends Pojo { TooManyConstructorPojo( Runnable injected ) { super( injected ); } public TooManyConstructorPojo() { super( null ); } } static abstract class AbstractPojo extends Pojo { AbstractPojo( Runnable injected ) { super( injected ); } } static class PojoWithRuntimeException { PojoWithRuntimeException() { throw new RuntimeException( getClass().getName() ); }; } static class PojoWithCheckedException { PojoWithCheckedException() throws Exception { throw new Exception( getClass().getName() ); }; } private static class UnaccessiblePojo { } static class DisposablePojo implements Disposable { boolean disposed; @Override public void dispose() { disposed = true; } } @Before public void setUp() { context = new Context(); } @Test public void set() { Runnable expected = mock( Runnable.class ); context.set( Runnable.class, expected ); Runnable actual = context.get( Runnable.class ); assertThat( actual ).isSameAs( expected ); } @Test public void setWithNullValue() { context.set( Runnable.class, null ); Runnable actual = context.get( Runnable.class ); assertThat( actual ).isNull(); } @Test public void setWithNullKey() { Throwable actual = thrownBy( () -> context.set( null, mock( Runnable.class ) ) ); assertThat( actual ) .hasMessage( Context.ARGUMENT_KEY_MUST_NOT_BE_NULL ) .isInstanceOf( IllegalArgumentException.class ); } @Test public void getWithNullKey() { Throwable actual = thrownBy( () -> context.get( null ) ); assertThat( actual ) .hasMessage( Context.ARGUMENT_KEY_MUST_NOT_BE_NULL ) .isInstanceOf( IllegalArgumentException.class ); } @Test public void getIfValueNotSet() { Runnable actual = context.get( Runnable.class ); assertThat( actual ).isNull(); } @Test public void getOfContext() { Context actual = context.get( Context.class ); assertThat( actual ).isSameAs( context ); } @Test public void create() { Object actual = context.create( Object.class ); assertThat( actual ).isNotNull(); } @Test public void createWithInjection() { Runnable expected = mock( Runnable.class ); context.set( Runnable.class, expected ); Pojo actual = context.create( Pojo.class ); assertThat( actual.injected ).isSameAs( expected ); } @Test public void createWithInjectionIfParameterIsNotAvailable() { Pojo actual = context.create( Pojo.class ); assertThat( actual.injected ).isNull(); } @Test public void createWithMultipleConstructorPojo() { Throwable actual = thrownBy( () -> context.create( TooManyConstructorPojo.class ) ); assertThat( actual ) .hasMessage( format( WRONG_CONSTRUCTOR_COUNT, TooManyConstructorPojo.class.getName() ) ) .isInstanceOf( IllegalArgumentException.class ); } @Test public void createInterfaceType() { Throwable actual = thrownBy( () -> context.create( Runnable.class ) ); assertThat( actual ) .hasMessage( format( INTERFACE_CANNOT_BE_INSTANTIATED, Runnable.class.getName() ) ) .isInstanceOf( IllegalArgumentException.class ); } @Test public void createAbstractType() { Throwable actual = thrownBy( () -> context.create( AbstractPojo.class ) ); assertThat( actual ) .hasMessage( format( ABSTRACT_TYPE_CANNOT_BE_INSTANTIATED, AbstractPojo.class.getName() ) ) .isInstanceOf( IllegalArgumentException.class ); } @Test public void createWithUnaccessiblePojo() { UnaccessiblePojo actual = context.create( UnaccessiblePojo.class ); assertThat( actual ).isNotNull(); } @Test public void createWithRuntimeExceptionThrownByPojoConstructor() { Throwable actual = thrownBy( () -> context.create( PojoWithRuntimeException.class ) ); assertThat( actual ) .hasMessage( PojoWithRuntimeException.class.getName() ) .isInstanceOf( RuntimeException.class ); } @Test public void createWithCheckedExceptionThrownByPojoConstructor() { Throwable actual = thrownBy( () -> context.create( PojoWithCheckedException.class ) ); assertThat( actual ) .hasCauseInstanceOf( Exception.class ) .isInstanceOf( IllegalStateException.class ); assertThat( actual.getCause() ) .hasMessage( PojoWithCheckedException.class.getName() ); } @Test public void dispose() { DisposablePojo value = new DisposablePojo(); context.set( DisposablePojo.class, value ); context.set( Object.class, new Object() ); context.dispose(); assertThat( value.disposed ).isTrue(); assertThat( context.get( DisposablePojo.class ) ).isNull(); assertThat( context.get( Object.class ) ).isNull(); } @Test( expected = IllegalArgumentException.class ) public void constructorWithNullArgument() { new Context( null ); } @Test public void createWithInjectionParameterProvider() { Runnable expected = mock( Runnable.class ); context = new Context( ( constructor, context ) -> new Object[] { expected } ); Pojo actual = context.create( Pojo.class ); assertThat( actual.injected ).isSameAs( expected ); } }