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