Skip to content

Commit

Permalink
cucumber#965: First draft of a working solution
Browse files Browse the repository at this point in the history
  • Loading branch information
JSlain committed Feb 29, 2016
1 parent 62637c8 commit 69316e0
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cucumber.runtime.java.spring;

import org.springframework.beans.factory.config.CustomScopeConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GlueScopeConfig {

@Bean
public CustomScopeConfigurer glueScopeConfigurer(){
CustomScopeConfigurer toReturn = new CustomScopeConfigurer();

toReturn.addScope("cucumber-glue", new GlueCodeScope());

return toReturn;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package cucumber.runtime.java.spring;

import java.io.IOException;

import org.springframework.asm.AnnotationVisitor;
import org.springframework.asm.ClassReader;
import org.springframework.asm.ClassVisitor;
import org.springframework.asm.ClassWriter;
import org.springframework.asm.Opcodes;
import org.springframework.asm.Type;
import org.springframework.test.context.ContextConfiguration;

public class GlueScopeConfigEnhancer implements Opcodes{

private class ASMClassLoader extends ClassLoader{
public Class defineClass(String name, byte[] content){
return defineClass(name, content, 0, content.length);
}
}

public Class enhance(Class class1) {
try {
String className = Type.getInternalName(class1);

ClassWriter cw = new ClassWriter(0);

ContextConfigurationClassVisitor contextCv = new ContextConfigurationClassVisitor(cw);

ClassReader cr = new ClassReader(className);
cr.accept(contextCv, 0);

return new ASMClassLoader().defineClass(className.replace('/', '.'), cw.toByteArray());

} catch (IOException e) {
throw new RuntimeException(e);
}
}

public class ContextConfigurationClassVisitor extends ClassVisitor{
public ContextConfigurationClassVisitor(ClassVisitor cv){
super(ASM5, cv);
}

@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if(Type.getDescriptor(ContextConfiguration.class).equals(desc)){
return new ContextConfigurationAnnotationVisitor(super.visitAnnotation(desc, visible));
}
return super.visitAnnotation(desc, visible);
}

}

public class ContextConfigurationAnnotationVisitor extends AnnotationVisitor {

public ContextConfigurationAnnotationVisitor(AnnotationVisitor av){
super(ASM5, av);
}

@Override
public AnnotationVisitor visitArray(String name) {
if("classes".equals(name)){
return new ContextConfigurationAnnotationArrayVisitor(super.visitArray(name));
}
return super.visitArray(name);
}
}

public class ContextConfigurationAnnotationArrayVisitor extends AnnotationVisitor {

public ContextConfigurationAnnotationArrayVisitor(AnnotationVisitor av){
super(ASM5, av);
}

@Override
public void visit(String name, Object value) {
super.visit(name, value);
}

@Override
public void visitEnd() {
visit(null, Type.getType(GlueScopeConfig.class));
super.visitEnd();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ private boolean isAnnotationInArray(Annotation annotation, Annotation[] annotati
@Override
public void start() {
if (stepClassWithSpringContext != null) {
testContextManager = new CucumberTestContextManager(stepClassWithSpringContext);
Class enhanced = new GlueScopeConfigEnhancer().enhance(stepClassWithSpringContext);
testContextManager = new CucumberTestContextManager(enhanced);
} else {
if (beanFactory == null) {
beanFactory = createFallbackContext();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package cucumber.runtime.java.spring;

import java.io.PrintWriter;

import org.junit.Assert;
import org.junit.Test;
import org.mockito.asm.ClassReader;
import org.mockito.asm.ClassWriter;
import org.mockito.asm.Type;
import org.mockito.asm.util.ASMifierClassVisitor;
import org.springframework.test.context.ContextConfiguration;

public class GlueScopeConfigEnhancerTest {

@Test
public void stepWithContextConfigurationAnnotationAndValue_enhance_GlueScopeConfigAdded() {
GlueScopeConfigEnhancer underTest = new GlueScopeConfigEnhancer();

Class enhanced = underTest.enhance(StepWithContexttConfigurationAnnotationAndValue.class);

Assert.assertNotNull(enhanced);

ContextConfiguration annotation = (ContextConfiguration) enhanced.getAnnotation(ContextConfiguration.class);

Assert.assertNotNull(annotation);
Assert.assertEquals(GlueScopeConfig.class, annotation.classes()[annotation.classes().length-1]);
}


@ContextConfiguration(classes=Object.class)
public static class StepWithContexttConfigurationAnnotationAndValue {
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import static org.junit.Assert.assertNotNull;

@ContextConfiguration("classpath:cucumber.xml")
@ContextConfiguration(value="classpath:cucumber.xml")
public class BellyStepdefs {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
//@RunWith(Cucumber.class)
@CucumberOptions(features={"classpath:cucumber/runtime/java/spring/springAnnotationBasedConfiguration.feature"})
public class RunCukesTest {

Expand Down

0 comments on commit 69316e0

Please sign in to comment.