1 /*
2  * Copyright (c) 2007 Mockito contributors
3  * This program is made available under the terms of the MIT License.
4  */
5 package org.mockitousage.annotation;
6 
7 import org.assertj.core.api.Assertions;
8 import org.junit.Before;
9 import org.junit.Test;
10 import org.mockito.InjectMocks;
11 import org.mockito.Mock;
12 import org.mockito.MockitoAnnotations;
13 import org.mockito.Spy;
14 import org.mockito.exceptions.base.MockitoException;
15 import org.mockito.internal.util.MockUtil;
16 import org.mockitousage.IMethods;
17 import org.mockitoutil.TestBase;
18 
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.TreeSet;
23 
24 import static org.junit.Assert.*;
25 
26 @SuppressWarnings({"unchecked", "unused"})
27 public class MockInjectionUsingSetterOrPropertyTest extends TestBase {
28 
29     private SuperUnderTesting superUnderTestWithoutInjection = new SuperUnderTesting();
30     @InjectMocks private SuperUnderTesting superUnderTest = new SuperUnderTesting();
31     @InjectMocks private BaseUnderTesting baseUnderTest = new BaseUnderTesting();
32     @InjectMocks private SubUnderTesting subUnderTest = new SubUnderTesting();
33     @InjectMocks private OtherBaseUnderTesting otherBaseUnderTest = new OtherBaseUnderTesting();
34     @InjectMocks private HasTwoFieldsWithSameType hasTwoFieldsWithSameType = new HasTwoFieldsWithSameType();
35 
36     private BaseUnderTesting baseUnderTestingInstance = new BaseUnderTesting();
37     @InjectMocks private BaseUnderTesting initializedBase = baseUnderTestingInstance;
38     @InjectMocks private BaseUnderTesting notInitializedBase;
39 
40     @Spy @InjectMocks private SuperUnderTesting initializedSpy = new SuperUnderTesting();
41     @Spy @InjectMocks private SuperUnderTesting notInitializedSpy;
42 
43     @Mock private Map<?, ?> map;
44     @Mock private List<?> list;
45     @Mock private Set<?> histogram1;
46     @Mock private Set<?> histogram2;
47     @Mock private IMethods candidate2;
48 
49     @Spy private TreeSet<String> searchTree = new TreeSet<String>();
50 
51     @Before
enforces_new_instances()52     public void enforces_new_instances() {
53         // initMocks called in TestBase Before method, so instances are not the same
54         MockitoAnnotations.initMocks(this);
55     }
56 
57     @Test
should_keep_same_instance_if_field_initialized()58     public void should_keep_same_instance_if_field_initialized() {
59         assertSame(baseUnderTestingInstance, initializedBase);
60     }
61 
62     @Test
should_initialize_annotated_field_if_null()63     public void should_initialize_annotated_field_if_null() {
64         assertNotNull(notInitializedBase);
65     }
66 
67     @Test
should_inject_mocks_in_spy()68     public void should_inject_mocks_in_spy() {
69         assertNotNull(initializedSpy.getAList());
70         assertTrue(MockUtil.isMock(initializedSpy));
71     }
72 
73     @Test
should_initialize_spy_if_null_and_inject_mocks()74     public void should_initialize_spy_if_null_and_inject_mocks() {
75         assertNotNull(notInitializedSpy);
76         assertNotNull(notInitializedSpy.getAList());
77         assertTrue(MockUtil.isMock(notInitializedSpy));
78     }
79 
80     @Test
should_inject_mocks_if_annotated()81     public void should_inject_mocks_if_annotated() {
82         MockitoAnnotations.initMocks(this);
83         assertSame(list, superUnderTest.getAList());
84     }
85 
86     @Test
should_not_inject_if_not_annotated()87     public void should_not_inject_if_not_annotated() {
88         MockitoAnnotations.initMocks(this);
89         assertNull(superUnderTestWithoutInjection.getAList());
90     }
91 
92     @Test
should_inject_mocks_for_class_hierarchy_if_annotated()93     public void should_inject_mocks_for_class_hierarchy_if_annotated() {
94         MockitoAnnotations.initMocks(this);
95         assertSame(list, baseUnderTest.getAList());
96         assertSame(map, baseUnderTest.getAMap());
97     }
98 
99     @Test
should_inject_mocks_by_name()100     public void should_inject_mocks_by_name() {
101         MockitoAnnotations.initMocks(this);
102         assertSame(histogram1, subUnderTest.getHistogram1());
103         assertSame(histogram2, subUnderTest.getHistogram2());
104     }
105 
106     @Test
should_inject_spies()107     public void should_inject_spies() {
108         MockitoAnnotations.initMocks(this);
109         assertSame(searchTree, otherBaseUnderTest.getSearchTree());
110     }
111 
112     @Test
should_insert_into_field_with_matching_name_when_multiple_fields_of_same_type_exists_in_injectee()113     public void should_insert_into_field_with_matching_name_when_multiple_fields_of_same_type_exists_in_injectee() {
114         MockitoAnnotations.initMocks(this);
115         assertNull("not injected, no mock named 'candidate1'", hasTwoFieldsWithSameType.candidate1);
116         assertNotNull("injected, there's a mock named 'candidate2'", hasTwoFieldsWithSameType.candidate2);
117     }
118 
119     @Test
should_instantiate_inject_mock_field_if_possible()120     public void should_instantiate_inject_mock_field_if_possible() throws Exception {
121         assertNotNull(notInitializedBase);
122     }
123 
124     @Test
should_keep_instance_on_inject_mock_field_if_present()125     public void should_keep_instance_on_inject_mock_field_if_present() throws Exception {
126         assertSame(baseUnderTestingInstance, initializedBase);
127     }
128 
129     @Test
should_report_nicely()130     public void should_report_nicely() throws Exception {
131         Object failing = new Object() {
132             @InjectMocks ThrowingConstructor failingConstructor;
133         };
134         try {
135             MockitoAnnotations.initMocks(failing);
136             fail();
137         } catch (MockitoException e) {
138             Assertions.assertThat(e.getMessage()).contains("failingConstructor").contains("constructor").contains("threw an exception");
139             Assertions.assertThat(e.getCause()).isInstanceOf(RuntimeException.class);
140         }
141     }
142 
143     static class ThrowingConstructor {
ThrowingConstructor()144         ThrowingConstructor() { throw new RuntimeException("aha"); }
145     }
146 
147     static class SuperUnderTesting {
148         private List<?> aList;
149 
getAList()150         public List<?> getAList() { return aList; }
151     }
152 
153     static class BaseUnderTesting extends SuperUnderTesting {
154         private Map<?, ?> aMap;
155 
getAMap()156         public Map<?, ?> getAMap() { return aMap; }
157     }
158 
159     static class OtherBaseUnderTesting extends SuperUnderTesting {
160         private TreeSet<?> searchTree;
161 
getSearchTree()162         public TreeSet<?> getSearchTree() { return searchTree; }
163     }
164 
165     static class SubUnderTesting extends BaseUnderTesting {
166         private Set<?> histogram1;
167         private Set<?> histogram2;
168 
getHistogram1()169         public Set<?> getHistogram1() { return histogram1; }
getHistogram2()170         public Set<?> getHistogram2() { return histogram2; }
171     }
172 
173     static class HasTwoFieldsWithSameType {
174         private IMethods candidate1;
175         private IMethods candidate2;
176     }
177 }
178