Commits

kubek2k committed ece446d

Initial annotation config support - not working

Comments (0)

Files changed (5)

springockito-annotations/pom.xml

     <parent>
         <groupId>org.kubek2k</groupId>
         <artifactId>springockito-parent</artifactId>
-        <version>1.0.4</version>
+        <version>1.0.5-SNAPSHOT</version>
     </parent>
 
     <scm>
             <artifactId>testng</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib</artifactId>
+            <version>2.2.2</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>

springockito-annotations/src/main/java/org/kubek2k/springockito/annotations/LoadContextWith.java

+package org.kubek2k.springockito.annotations;
+
+import org.springframework.test.context.support.AbstractGenericContextLoader;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface LoadContextWith {
+    Class<? extends AbstractGenericContextLoader> value();
+}

springockito-annotations/src/main/java/org/kubek2k/springockito/annotations/SpringockitoContextLoader.java

 package org.kubek2k.springockito.annotations;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.util.*;
+import java.util.logging.Logger;
 
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
 import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.MessageSourceResolvable;
+import org.springframework.context.NoSuchMessageException;
 import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.core.env.Environment;
+import org.springframework.core.io.Resource;
+import org.springframework.test.context.ContextConfigurationAttributes;
+import org.springframework.test.context.ContextLoader;
+import org.springframework.test.context.MergedContextConfiguration;
+import org.springframework.test.context.SmartContextLoader;
+import org.springframework.test.context.support.AbstractGenericContextLoader;
+import org.springframework.test.context.support.DelegatingSmartContextLoader;
 import org.springframework.test.context.support.GenericXmlContextLoader;
 
-public class SpringockitoContextLoader extends GenericXmlContextLoader {
+public class SpringockitoContextLoader implements ContextLoader, SmartContextLoader {
+
+    private static final Logger LOGGER = Logger.getLogger(SpringockitoContextLoader.class.getName());
 
     private Map<String, DesiredMockitoBeansFinder.MockProperties<ReplaceWithMock>> mockedBeans
             = new HashMap<String, DesiredMockitoBeansFinder.MockProperties<ReplaceWithMock>>();
     private MockitoBeansDefiner mockitoBeansDefiner = new MockitoBeansDefiner();
     private MockitoSpiesDefiner mockitoSpiesDefiner = new MockitoSpiesDefiner();
 
-    @Override
-    protected void customizeContext(GenericApplicationContext context) {
-        super.customizeContext(context);
-        registerMocks(context, mockedBeans);
-        registerSpies(context, spiedBeans);
-    }
+    private AbstractGenericContextLoader wrappedLoader;
 
     private void registerMocks(GenericApplicationContext context,
                                Map<String, DesiredMockitoBeansFinder.MockProperties<ReplaceWithMock>> mockedBeans) {
         }
     }
 
-    @Override
-    protected String[] generateDefaultLocations(Class<?> clazz) {
+    private void findMockedAndSpiedBeansLocations(Class<?> clazz) {
         this.mockedBeans = mockedBeansFinder.findMockedBeans(clazz);
         this.spiedBeans = mockedBeansFinder.findSpiedBeans(clazz);
-
-        return super.generateDefaultLocations(clazz);
-
     }
 
-    @Override
-    protected String[] modifyLocations(Class<?> clazz, String... locations) {
-        this.mockedBeans = mockedBeansFinder.findMockedBeans(clazz);
-        this.spiedBeans = mockedBeansFinder.findSpiedBeans(clazz);
+    /**
+     * Invoked by Spring < 3.1
+     * @param clazz
+     * @param locations
+     * @return
+     */
+    public String[] processLocations(Class<?> clazz, String... locations) {
+        findMockedAndSpiedBeansLocations(clazz);
+        initWrappedContextLoader(clazz);
+        return wrappedLoader.processLocations(clazz, locations);
+    }
 
-        return super.modifyLocations(clazz, locations);
+    /**
+     * Invoked by Spring >= 3.1
+     * @param configAttributes
+     */
+    public void processContextConfiguration(ContextConfigurationAttributes configAttributes) {
+        findMockedAndSpiedBeansLocations(configAttributes.getDeclaringClass());
+        initWrappedContextLoader(configAttributes.getDeclaringClass());
+        wrappedLoader.processContextConfiguration(configAttributes);
+    }
+
+    private void initWrappedContextLoader(Class<?> clazz) {
+        if (this.wrappedLoader == null) {
+            try {
+                LoadContextWith loadContextWith = clazz.getAnnotation(LoadContextWith.class);
+                if (loadContextWith != null && loadContextWith.value() != null) {
+                    this.wrappedLoader = loadContextWith.value().newInstance();
+                } else {
+                    this.wrappedLoader = new GenericXmlContextLoader();
+                }
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        } else {
+            LOGGER.warning("The init of re-init wrapped context loader invoked - please check your inheritance hierarchy");
+        }
+    }
+
+    /**
+     * Invoked by Spring < 3.1
+     * @param locations
+     * @return
+     * @throws Exception
+     */
+    public ApplicationContext loadContext(String... locations) throws Exception {
+        // we can cast here, the instance is returned as GenericApplicationContext {@link AbstractGenericContextLoader}
+        GenericApplicationContext context = (GenericApplicationContext) wrappedLoader.loadContext(locations);
+
+        registerMocksAndSpies(context);
+
+        context.refresh();
+
+        return context;
+    }
+
+    /**
+     * Invoked by Spring >= 3.1
+     * @param mergedConfig
+     * @return
+     * @throws Exception
+     */
+    public ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
+        GenericApplicationContext context = (GenericApplicationContext) wrappedLoader.loadContext(mergedConfig);
+
+        registerMocksAndSpies(context);
+
+        return context;
+    }
+
+    private void registerMocksAndSpies(GenericApplicationContext context) {
+        registerMocks(context, this.mockedBeans);
+        registerSpies(context, this.spiedBeans);
     }
 }

springockito-annotations/src/test/java/org/kubek2k/springockito/annotations/AnnotationBasedConfigurationIntegrationTest.java

+package org.kubek2k.springockito.annotations;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
+import org.testng.annotations.Test;
+
+import static org.mockito.Mockito.verify;
+
+@ContextConfiguration(loader = SpringockitoContextLoader.class, classes = AnnotationBasedConfigurationIntegrationTest.Config.class)
+@LoadContextWith(AnnotationConfigContextLoader.class)
+public class AnnotationBasedConfigurationIntegrationTest extends AbstractTestNGSpringContextTests {
+
+    @Configuration
+    static class Config {
+        @Bean(name = "outerBean")
+        public OuterBean outerBean() {
+            OuterBean outerBean = new OuterBean();
+
+            outerBean.setInnerBean(innerBean());
+
+            return outerBean;
+        }
+
+        @Bean(name = "innerBean")
+        public InnerBean innerBean() {
+            return new InnerBean();
+        }
+    }
+
+    @ReplaceWithMock
+    @Autowired
+    private InnerBean innerBean;
+
+    @Autowired
+    private OuterBean outerBean;
+
+    @Test
+    @DirtiesContext
+    public void shouldUseMockInsteadOfOriginalBean() {
+        outerBean.doSomething();
+
+        verify(innerBean).doSomething();
+    }
+
+}

springockito-parent/pom.xml

 
     <properties>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-      <spring.version>3.0.5.RELEASE</spring.version>
+      <spring.version>3.1.2.RELEASE</spring.version>
     </properties>
 
   <dependencyManagement>