View Javadoc
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         // Look-up beans by name only.
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         // Look-up beans by name and type.
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         // Look-up beans by type only.
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 /* TestWebApplicationContext(); */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 }