1
2
3
4
5
6 package mockit.integration.springframework;
7
8 import static org.junit.jupiter.api.Assertions.assertEquals;
9 import static org.junit.jupiter.api.Assertions.assertFalse;
10 import static org.junit.jupiter.api.Assertions.assertNotNull;
11 import static org.junit.jupiter.api.Assertions.assertSame;
12 import static org.junit.jupiter.api.Assertions.assertThrows;
13
14 import mockit.Injectable;
15 import mockit.Tested;
16
17 import org.junit.jupiter.api.BeforeAll;
18 import org.junit.jupiter.api.Test;
19 import org.springframework.beans.factory.BeanFactory;
20 import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
21 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
22 import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.beans.factory.support.DefaultListableBeanFactory;
24
25 final class SpringIntegrationTest {
26 @BeforeAll
27 static void applySpringIntegration() {
28 new FakeBeanFactory();
29 }
30
31 public static class ExampleSUT {
32 @Autowired
33 Collaborator collaborator;
34 @Autowired
35 Dependency dependency;
36 }
37
38 public interface Dependency {
39 }
40
41 static final class DependencyImpl implements Dependency {
42 }
43
44 public interface AnotherDependency {
45 }
46
47 static final class AnotherDependencyImpl implements AnotherDependency {
48 Dependency subDep;
49 }
50
51 static class Collaborator {
52 @Autowired
53 Runnable action;
54 }
55
56 @Tested
57 DependencyImpl dependency;
58 @Tested(fullyInitialized = true)
59 ExampleSUT exampleSUT;
60 @Injectable
61 Runnable action;
62
63 @Tested
64 Class<?> resolveAnotherDependency(Class<? extends AnotherDependency> anInterface) {
65 assertSame(AnotherDependency.class, anInterface);
66 return AnotherDependencyImpl.class;
67 }
68
69 @Test
70 void lookupTestedObjectsAndInjectedDependenciesThroughTheBeanFactory() {
71 BeanFactory beanFactory = new DefaultListableBeanFactory();
72 assertTestedObjectsAndDependencies(beanFactory);
73 }
74
75 @Test
76 void lookupTestedObjectsAndInjectedDependenciesThroughTheWebApplicationContext() {
77 BeanFactory beanFactory = new TestWebApplicationContext();
78 assertTestedObjectsAndDependencies(beanFactory);
79 }
80
81 @Test
82 void lookUpBeanByNameWithUnknownNameUsingBeanFactory() {
83 BeanFactory beanFactory = new DefaultListableBeanFactory();
84 assertNoSuchBeanDefinitionForUnknownBeanName(beanFactory);
85 }
86
87 @Test
88 void lookUpBeanByNameWithUnknownNameUsingWebApplicationContext() {
89 BeanFactory beanFactory = new TestWebApplicationContext();
90 assertNoSuchBeanDefinitionForUnknownBeanName(beanFactory);
91 }
92
93 @Test
94 void lookUpBeanByNameAndTypeWithUnknownNameAndTypeUsingBeanFactory() {
95 BeanFactory beanFactory = new DefaultListableBeanFactory();
96 assertNoSuchBeanDefinitionForUnknownBeanNameAndType(beanFactory);
97 }
98
99 @Test
100 void lookUpBeanByNameAndTypeWithUnknownNameAndTypeUsingWebApplicationContext() {
101 BeanFactory beanFactory = new TestWebApplicationContext();
102 assertNoSuchBeanDefinitionForUnknownBeanNameAndType(beanFactory);
103 }
104
105 @Test
106 void lookUpBeanByNameAndTypeWithWrongTypeUsingBeanFactory() {
107 BeanFactory beanFactory = new DefaultListableBeanFactory();
108 assertBeanNotOfRequiredTypeForWrongBeanType(beanFactory);
109 }
110
111 @Test
112 void lookUpBeanByNameAndTypeWithWrongTypeUsingWebApplicationContext() {
113 BeanFactory beanFactory = new TestWebApplicationContext();
114 assertBeanNotOfRequiredTypeForWrongBeanType(beanFactory);
115 }
116
117 @SuppressWarnings("ReuseOfLocalVariable")
118 void assertTestedObjectsAndDependencies(BeanFactory beanFactory) {
119 assertSame(dependency, exampleSUT.dependency);
120
121
122 Dependency dependencyBean = (Dependency) beanFactory.getBean("dependency");
123 assertSame(dependency, dependencyBean);
124
125 Collaborator collaboratorBean = (Collaborator) beanFactory.getBean("collaborator");
126 assertSame(exampleSUT.collaborator, collaboratorBean);
127 assertSame(action, exampleSUT.collaborator.action);
128
129 ExampleSUT sut = (ExampleSUT) beanFactory.getBean("exampleSUT");
130 assertSame(exampleSUT, sut);
131
132
133 dependencyBean = beanFactory.getBean("dependency", Dependency.class);
134 assertSame(dependency, dependencyBean);
135
136 collaboratorBean = beanFactory.getBean("collaborator", Collaborator.class);
137 assertSame(exampleSUT.collaborator, collaboratorBean);
138
139 sut = beanFactory.getBean("exampleSUT", ExampleSUT.class);
140 assertSame(exampleSUT, sut);
141
142 AnotherDependency anotherDependencyBean = beanFactory.getBean("anotherDependency", AnotherDependency.class);
143 assertNotNull(anotherDependencyBean);
144
145
146 dependencyBean = beanFactory.getBean(Dependency.class);
147 assertSame(dependency, dependencyBean);
148
149 collaboratorBean = beanFactory.getBean(Collaborator.class);
150 assertSame(exampleSUT.collaborator, collaboratorBean);
151
152 sut = beanFactory.getBean(ExampleSUT.class);
153 assertSame(exampleSUT, sut);
154
155 anotherDependencyBean = beanFactory.getBean(AnotherDependency.class);
156 assertNotNull(anotherDependencyBean);
157 assertSame(dependency, ((AnotherDependencyImpl) anotherDependencyBean).subDep);
158 }
159
160 void assertNoSuchBeanDefinitionForUnknownBeanName(BeanFactory beanFactory) {
161 Throwable throwable = assertThrows(NoSuchBeanDefinitionException.class, () -> {
162 beanFactory.getBean("undefined");
163 });
164 assertEquals("No bean named 'undefined' available", throwable.getMessage());
165 }
166
167 void assertNoSuchBeanDefinitionForUnknownBeanNameAndType(BeanFactory beanFactory) {
168 Throwable throwable = assertThrows(NoSuchBeanDefinitionException.class, () -> {
169 beanFactory.getBean("undefined", Process.class);
170 });
171 assertEquals("No qualifying bean of type 'java.lang.Process' available: with bean name \"undefined\"",
172 throwable.getMessage());
173 }
174
175 void assertBeanNotOfRequiredTypeForWrongBeanType(BeanFactory beanFactory) {
176 Throwable throwable = assertThrows(BeanNotOfRequiredTypeException.class, () -> {
177 beanFactory.getBean("dependency", Collaborator.class);
178 });
179 assertEquals("Bean named 'dependency' is expected to be of type "
180 + "'mockit.integration.springframework.SpringIntegrationTest$Collaborator' "
181 + "but was actually of type 'mockit.integration.springframework.SpringIntegrationTest$DependencyImpl'",
182 throwable.getMessage());
183 }
184
185 @Test
186 void lookUpBeanByTypeHavingInjectableInstance(@Injectable Collaborator collaborator) {
187 BeanFactory beanFactory = new DefaultListableBeanFactory();
188
189 Collaborator collaboratorBean = beanFactory.getBean(Collaborator.class);
190
191 assertSame(collaborator, collaboratorBean);
192 }
193
194 @Test
195 void lookUpBeanByTypeTwiceHavingSingleInjectableInstance(@Injectable Collaborator collaborator) {
196 BeanFactory beanFactory = new DefaultListableBeanFactory();
197
198 Collaborator collaboratorBean1 = beanFactory.getBean(Collaborator.class);
199 Collaborator collaboratorBean2 = beanFactory.getBean(Collaborator.class);
200
201 assertSame(collaborator, collaboratorBean1);
202 assertSame(collaborator, collaboratorBean2);
203 }
204
205 static class Level1 {
206 @Autowired
207 Level2 level2;
208 }
209
210 static class Level2 {
211 @Autowired
212 Level3 level3;
213 }
214
215 static class Level3 {
216 Level3(@SuppressWarnings("unused") String str) {
217 }
218 }
219
220 @Test
221 public void lookupBeanWithDependencyOnAnotherWhichAlsoDependsOnAnotherWhichHasAOneArgumentConstructor() {
222 Throwable throwable = assertThrows(IllegalStateException.class, () -> {
223 BeanFactory beanFactory = new TestWebApplicationContext();
224 Level1 level1 = beanFactory.getBean(Level1.class);
225
226 assertNotNull(level1);
227 assertNotNull(level1.level2);
228 assertNotNull(level1.level2.level3);
229 });
230 assertEquals("Missing @Tested or @Injectable for parameter \"str\" in constructor Level3(String str)" + "\r\n"
231 + " when initializing field \"Level3 level3\"" + "\r\n" + " when initializing field \"Level2 level2\""
232 + "\r\n" + " of @Tested object \"Level1 level1\"", throwable.getMessage());
233 }
234
235 @Test
236 void failToLookupBeanButCatchExceptionAndThrowAnother_stillShouldIncludedFilteredStackTrace() {
237 BeanFactory beanFactory = new TestWebApplicationContext();
238
239 try {
240 beanFactory.getBean(Level1.class);
241 } catch (IllegalStateException e) {
242 for (StackTraceElement ste : e.getStackTrace()) {
243 assertFalse(ste.getClassName().startsWith("mockit.internal."), ste.toString());
244 }
245 }
246 }
247 }