Home | History | Annotate | Download | only in reflection
      1 /*
      2  * Copyright (c) 2007 Mockito contributors
      3  * This program is made available under the terms of the MIT License.
      4  */
      5 
      6 package org.mockito.internal.util.reflection;
      7 
      8 
      9 import org.junit.After;
     10 import org.junit.Test;
     11 import org.junit.runner.RunWith;
     12 import org.mockito.Matchers;
     13 import org.mockito.Mock;
     14 import org.mockito.exceptions.base.MockitoException;
     15 import org.mockito.internal.util.reflection.FieldInitializer.ConstructorArgumentResolver;
     16 import org.mockito.internal.util.reflection.FieldInitializer.ParameterizedConstructorInstantiator;
     17 import org.mockito.junit.MockitoJUnitRunner;
     18 
     19 import java.io.IOException;
     20 import java.lang.reflect.Field;
     21 import java.util.Map;
     22 import java.util.Observer;
     23 import java.util.Set;
     24 
     25 import static org.assertj.core.api.Assertions.assertThat;
     26 import static org.junit.Assert.assertNotNull;
     27 import static org.junit.Assert.fail;
     28 import static org.mockito.BDDMockito.given;
     29 import static org.mockito.Mockito.mock;
     30 
     31 
     32 @SuppressWarnings("unchecked")
     33 @RunWith(MockitoJUnitRunner.class)
     34 public class ParameterizedConstructorInstantiatorTest {
     35 
     36     private Set<?> whateverForNow;
     37     private OneConstructor withOneConstructor;
     38     private MultipleConstructor withMultipleConstructor;
     39     private NoArgConstructor withNoArgConstructor;
     40     private ThrowingConstructor withThrowingConstructor;
     41     private VarargConstructor withVarargConstructor;
     42 
     43     @After
     44     public void ensure_instances_to_create_are_null() {
     45         withMultipleConstructor = null;
     46         withOneConstructor = null;
     47         withNoArgConstructor = null;
     48         withThrowingConstructor = null;
     49         withVarargConstructor = null;
     50     }
     51 
     52     @Mock private ConstructorArgumentResolver resolver;
     53 
     54     @Test
     55     public void should_be_created_with_an_argument_resolver() throws Exception {
     56         new ParameterizedConstructorInstantiator(this, field("whateverForNow"), resolver);
     57     }
     58 
     59     @Test
     60     public void should_fail_if_no_parameterized_constructor_found___excluding_inner_and_others_kind_of_types() throws Exception {
     61         try {
     62             new ParameterizedConstructorInstantiator(this, field("withNoArgConstructor"), resolver).instantiate();
     63             fail();
     64         } catch (MockitoException me) {
     65             assertThat(me.getMessage()).contains("no parameterized constructor").contains("withNoArgConstructor").contains("NoArgConstructor");
     66         }
     67     }
     68 
     69     @Test
     70     public void should_instantiate_type_if_resolver_provide_matching_types() throws Exception {
     71         Observer observer = mock(Observer.class);
     72         Map map = mock(Map.class);
     73         given(resolver.resolveTypeInstances(Matchers.<Class<?>[]>anyVararg())).willReturn(new Object[]{ observer, map });
     74 
     75         new ParameterizedConstructorInstantiator(this, field("withMultipleConstructor"), resolver).instantiate();
     76 
     77         assertNotNull(withMultipleConstructor);
     78         assertNotNull(withMultipleConstructor.observer);
     79         assertNotNull(withMultipleConstructor.map);
     80     }
     81 
     82     @Test
     83     public void should_fail_if_an_argument_instance_type_do_not_match_wanted_type() throws Exception {
     84         Observer observer = mock(Observer.class);
     85         Set<?> wrongArg = mock(Set.class);
     86         given(resolver.resolveTypeInstances(Matchers.<Class<?>[]>anyVararg())).willReturn(new Object[]{ observer, wrongArg });
     87 
     88         try {
     89             new ParameterizedConstructorInstantiator(this, field("withMultipleConstructor"), resolver).instantiate();
     90             fail();
     91         } catch (MockitoException e) {
     92             assertThat(e.getMessage()).contains("argResolver").contains("incorrect types");
     93         }
     94     }
     95 
     96     @Test
     97     public void should_report_failure_if_constructor_throws_exception() throws Exception {
     98         given(resolver.resolveTypeInstances(Matchers.<Class<?>[]>anyVararg())).willReturn(new Object[]{ null });
     99 
    100         try {
    101             new ParameterizedConstructorInstantiator(this, field("withThrowingConstructor"), resolver).instantiate();
    102             fail();
    103         } catch (MockitoException e) {
    104             assertThat(e.getMessage()).contains("constructor").contains("raised an exception");
    105         }
    106     }
    107 
    108     @Test
    109     public void should_instantiate_type_with_vararg_constructor() throws Exception {
    110         Observer[] vararg = new Observer[] {  };
    111         given(resolver.resolveTypeInstances(Matchers.<Class<?>[]>anyVararg())).willReturn(new Object[]{ "", vararg});
    112 
    113         new ParameterizedConstructorInstantiator(this, field("withVarargConstructor"), resolver).instantiate();
    114 
    115         assertNotNull(withVarargConstructor);
    116     }
    117 
    118     private Field field(String fieldName) throws NoSuchFieldException {
    119         Field field = this.getClass().getDeclaredField(fieldName);
    120         field.setAccessible(true);
    121         return field;
    122     }
    123 
    124     private static class NoArgConstructor {
    125         NoArgConstructor() { }
    126     }
    127 
    128     private static class OneConstructor {
    129         public OneConstructor(Observer observer) { }
    130     }
    131 
    132     private static class ThrowingConstructor {
    133         public ThrowingConstructor(Observer observer) throws IOException { throw new IOException(); }
    134     }
    135 
    136     private static class MultipleConstructor extends OneConstructor {
    137         Observer observer;
    138         Map map;
    139 
    140         public MultipleConstructor(Observer observer) { this(observer, null); }
    141         public MultipleConstructor(Observer observer, Map map) {
    142             super(observer);
    143             this.observer = observer;
    144             this.map = map;
    145         }
    146     }
    147 
    148     private static class VarargConstructor {
    149         VarargConstructor(String whatever, Observer... observers) { }
    150     }
    151 }
    152