Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spring autoconfiguration for JGiven #153

Merged
merged 2 commits into from
Oct 27, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.tngtech.jgiven.integration.spring;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.config.AopNamespaceUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;

public class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {

private final Log logger = LogFactory.getLog(getClass());

private static final String BEAN_NAME = "com.tngtech.jgiven.integration.spring.jGivenStageAutoProxyCreator";

@Override
public BeanDefinition parse( Element element, ParserContext parserContext ) {
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary( parserContext, element );
if( !parserContext.getRegistry().containsBeanDefinition( BEAN_NAME ) ) {
Object eleSource = parserContext.extractSource( element );

// create Interceptor
RootBeanDefinition interceptorDef = new RootBeanDefinition( SpringStepMethodInterceptor.class );
interceptorDef.setScope( AbstractBeanDefinition.SCOPE_PROTOTYPE );
interceptorDef.setSource( eleSource );
interceptorDef.setRole( BeanDefinition.ROLE_INFRASTRUCTURE );
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName( interceptorDef );
logger.debug( "Registered SpringStepMethodInterceptor with name " + interceptorName );

// create Scenario Executor
RootBeanDefinition executorDef = new RootBeanDefinition( SpringScenarioExecutor.class );
executorDef.setScope( AbstractBeanDefinition.SCOPE_PROTOTYPE );
executorDef.setSource( eleSource );
interceptorDef.setRole( BeanDefinition.ROLE_INFRASTRUCTURE );
String executorName = parserContext.getReaderContext().registerWithGeneratedName( executorDef );
logger.debug( "Registered SpringScenarioExecutor with name " + executorName );

// create AutoProxyCreator
RootBeanDefinition autoProxyCreatorDef = new RootBeanDefinition( JGivenStageAutoProxyCreator.class );
autoProxyCreatorDef.setRole( BeanDefinition.ROLE_INFRASTRUCTURE );
parserContext.getRegistry().registerBeanDefinition( BEAN_NAME, autoProxyCreatorDef );

CompositeComponentDefinition componentDefinition = new CompositeComponentDefinition( element.getTagName(), eleSource );
componentDefinition.addNestedComponent( new BeanComponentDefinition( interceptorDef, interceptorName ) );
componentDefinition.addNestedComponent( new BeanComponentDefinition( executorDef, executorName ) );
componentDefinition.addNestedComponent( new BeanComponentDefinition( autoProxyCreatorDef, BEAN_NAME ) );
parserContext.registerComponent( componentDefinition );
}
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.tngtech.jgiven.integration.spring;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
* Enables JGiven's spring support. To be used on @{@link Configuration} classes as follows:
*
* <pre class="code">
* &#064;Configuration
* &#064;EnableJGiven
* public class AppConfig {
* ...
* }</pre>
*
*
* @since 0.8.1
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(JGivenSpringConfiguration.class)
@Documented
public @interface EnableJGiven {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.tngtech.jgiven.integration.spring;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class JGivenNamespaceHandler extends NamespaceHandlerSupport {

@Override
public void init() {
registerBeanDefinitionParser( "annotation-driven", new AnnotationDrivenBeanDefinitionParser() );
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.tngtech.jgiven.integration.spring;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.context.annotation.Scope;

/**
* {@code @Configuration} class that registers all beans an post-processors
* for full JGiven Spring support
*
* @since 0.8.1
*/
@Configuration
public class JGivenSpringConfiguration {

@Bean
@Scope("prototype")
public SpringStepMethodInterceptor springStepMethodInterceptor() {
return new SpringStepMethodInterceptor();
}

@Bean
@Scope("prototype")
public SpringScenarioExecutor springScenarioExecutor() {
return new SpringScenarioExecutor();
}

/*
* configure support for {@link JGivenStage} annotation
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public JGivenStageAutoProxyCreator jGivenStageAutoProxyCreator() {
return new JGivenStageAutoProxyCreator();
}

}
1 change: 1 addition & 0 deletions jgiven-spring/src/main/resources/META-INF/spring.handlers
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
http\://jgiven.org/jgiven-spring=com.tngtech.jgiven.integration.spring.JGivenNamespaceHandler
1 change: 1 addition & 0 deletions jgiven-spring/src/main/resources/META-INF/spring.schemas
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
http\://jgiven.org/schemas/jgiven-spring.xsd=com/tngtech/jgiven/integration/spring/jgiven-spring.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="http://jgiven.org/jgiven-spring" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://jgiven.org/jgiven-spring">
<xs:element name="annotation-driven">
<xs:annotation>
<xs:documentation>
Use this to enable the annotation driven JGiven support. This declaration automatically registers a default SpringStepMethodInterceptor and SpringScenarioExecutor.
Additionally support for the @JGivenStage is configured.
</xs:documentation>
</xs:annotation>
<xs:complexType />
</xs:element>
</xs:schema>
Original file line number Diff line number Diff line change
@@ -1,38 +1,18 @@
package com.tngtech.jgiven.integration.spring.test;
package com.tngtech.jgiven.integration.spring.config;

import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

import com.tngtech.jgiven.integration.spring.JGivenStageAutoProxyCreator;
import com.tngtech.jgiven.integration.spring.SpringScenarioExecutor;
import com.tngtech.jgiven.integration.spring.SpringStepMethodInterceptor;
import com.tngtech.jgiven.integration.spring.EnableJGiven;

@Configuration
// auto configuration for JGiven
@EnableJGiven
@ComponentScan(basePackages = "com.tngtech.jgiven.integration.spring.test")
public class TestSpringConfig {

@Bean
@Scope("prototype")
public SpringStepMethodInterceptor springStepMethodInterceptor() {
return new SpringStepMethodInterceptor();
}

@Bean
@Scope("prototype")
public SpringScenarioExecutor springScenarioExecutor() {
return new SpringScenarioExecutor();
}

/*
* configure support for {@link JGivenStage} annotation
*/
@Bean
public JGivenStageAutoProxyCreator jGivenStageAutoProxyCreator() {
return new JGivenStageAutoProxyCreator();
}

/*
* example for non-invasive usage of the {@link SpringStepMethodInterceptor}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.tngtech.jgiven.integration.spring.SpringScenarioTest;
import com.tngtech.jgiven.integration.spring.config.TestSpringConfig;

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( classes = TestSpringConfig.class )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.tngtech.jgiven.integration.spring.SpringScenarioTest;
import com.tngtech.jgiven.integration.spring.config.TestSpringConfig;

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( classes = TestSpringConfig.class )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.springframework.stereotype.Component;

import com.tngtech.jgiven.integration.spring.JGivenStage;
import com.tngtech.jgiven.integration.spring.config.TestSpringConfig;

/**
* example for a Spring Bean that is used as a step
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.tngtech.jgiven.integration.spring.SpringScenarioTest;
import com.tngtech.jgiven.integration.spring.config.TestSpringConfig;

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( classes = TestSpringConfig.class )
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.tngtech.jgiven.integration.spring.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.tngtech.jgiven.integration.spring.SpringScenarioTest;

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration("/jgiven-spring.xml")
public class XmlConfiguredSpringScenarioTestTest extends SpringScenarioTest<AnnotatedStage, AnnotatedStage, AnnotatedStage> {

@Test
public void spring_can_inject_beans_into_stages() {
given().a_stage_that_is_a_spring_component();
when().methods_on_this_component_are_called();
then().beans_are_injected();
}
}
13 changes: 13 additions & 0 deletions jgiven-spring/src/test/resources/jgiven-spring.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jgiven="http://jgiven.org/jgiven-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://jgiven.org/jgiven-spring http://jgiven.org/schemas/jgiven-spring.xsd">

<context:component-scan base-package="com.tngtech.jgiven.integration.spring.test" />
<jgiven:annotation-driven/>

</beans>