Skip to content

Commit

Permalink
Improve support for Spring TestContext Framework 4.0
Browse files Browse the repository at this point in the history
- handle meta-annotations
- added spring-boot project/test sample
  • Loading branch information
pniederw committed Sep 8, 2014
1 parent 46d8365 commit 718bf42
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 10 deletions.
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include "spock-core"
include "spock-specs"
include "spock-spring"
include "spock-boot"
include "spock-guice"
include "spock-tapestry"
include "spock-unitils"
Expand Down
15 changes: 15 additions & 0 deletions spock-boot/boot.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
def springVersion = "4.1.0.RELEASE"
def bootVersion = "1.1.6.RELEASE"

dependencies {
compile "org.springframework:spring-core:$springVersion"
compile "org.springframework.boot:spring-boot:$bootVersion"
compile "org.springframework.boot:spring-boot-autoconfigure:$bootVersion"

testCompile project(":spock-core")
testCompile "org.springframework:spring-context:$springVersion"
testCompile "org.springframework:spring-test:$springVersion"

testRuntime project(":spock-spring")
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2012-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.spockframework.boot;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import org.spockframework.boot.service.HelloWorldService;

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class SimpleBootApp implements CommandLineRunner {
@Autowired
private HelloWorldService helloWorldService;

@Override
public void run(String... args) {
System.out.println(this.helloWorldService.getHelloMessage());
}

public static void main(String[] args) throws Exception {
SpringApplication.run(SimpleBootApp.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2012-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.spockframework.boot.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class HelloWorldService {

@Value("${name:World}")
private String name;

public String getHelloMessage() {
return "Hello " + this.name;
}

}
1 change: 1 addition & 0 deletions spock-boot/src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name: Spock
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.spockframework.boot

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.SpringApplicationConfiguration
import org.springframework.context.ApplicationContext

import spock.lang.Specification

/**
* Spock test for {@link org.spockframework.boot.SimpleBootApp}.
* Adapted from https://github.com/spring-projects/spring-boot/blob/master/spring-boot-samples/
* spring-boot-sample-simple/src/test/java/sample/simple/SpringTestSampleSimpleApplicationTests.java.
*
* @author Dave Syer
* @author Peter Niederwieser
*/
@SpringApplicationConfiguration(classes = SimpleBootApp.class)
class SimpleBootAppIntegrationSpec extends Specification {
@Autowired
ApplicationContext ctx

def "test context loads"() {
expect:
ctx != null
ctx.containsBean("helloWorldService")
ctx.containsBean("simpleBootApp")
}
}
9 changes: 7 additions & 2 deletions spock-spring/spring.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ apply from: script("publishMaven")
displayName = "Spock Framework - Spring Module"

description = "Spock's Spring Module makes it possible to use Spring's TestContext framework together with Spock. \
Both Spring 2.5.x and 3.x are supported."
Supports Spring 2.5.x, 3.x, and 4.x."

def springVersion = "3.2.2.RELEASE"
def springVersion = "2.5.6.SEC01"

if (springVersion.startsWith("2.")) {
sourceSets.test.groovy.exclude "**/*ContextHierarchyExample.groovy"
}

dependencies {
compile project(":spock-core")
Expand All @@ -18,6 +22,7 @@ dependencies {
testCompile "org.springframework:spring-jdbc:$springVersion"
testCompile "org.springframework:spring-tx:$springVersion"
testCompile "javax.inject:javax.inject:1"

testRuntime libs.h2database
testRuntime libs.log4j
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,40 @@

package org.spockframework.spring;

import org.spockframework.runtime.extension.AbstractGlobalExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.ProfileValueUtils;
import org.springframework.test.context.ContextConfiguration;
import java.lang.annotation.*;
import java.lang.reflect.*;

import org.spockframework.runtime.extension.AbstractGlobalExtension;
import org.spockframework.runtime.AbstractRunListener;
import org.spockframework.runtime.model.*;
import org.spockframework.util.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.ProfileValueUtils;
import org.springframework.test.context.ContextConfiguration;

import spock.lang.Shared;

@NotThreadSafe
public class SpringExtension extends AbstractGlobalExtension {
// since Spring 3.2.2
@SuppressWarnings("unchecked")
private static final Class<? extends Annotation> contextHierarchyClass =
(Class) ReflectionUtil.loadClassIfAvailable("org.springframework.test.context.ContextHierarchy");

// since Spring 4.0
private static final Method findAnnotationDescriptorForTypesMethod;

static {
Class<?> metaAnnotationUtilsClass =
ReflectionUtil.loadClassIfAvailable("org.springframework.test.util.MetaAnnotationUtils");
findAnnotationDescriptorForTypesMethod = metaAnnotationUtilsClass == null ? null :
ReflectionUtil.getMethodBySignature(metaAnnotationUtilsClass,
"findAnnotationDescriptorForTypes", Class.class, Class[].class);
}

public void visitSpec(SpecInfo spec) {
if (!spec.isAnnotationPresent(ContextConfiguration.class)
// avoid compile-time dependency on Spring 3.2.2
&& !ReflectionUtil.isAnnotationPresent(spec.getReflection(),
"org.springframework.test.context.ContextHierarchy")) return;
if (!isSpringSpec(spec)) return;

checkNoSharedFieldsInjected(spec);

Expand All @@ -54,6 +70,15 @@ public void error(ErrorInfo error) {
spec.addCleanupSpecInterceptor(interceptor);
}

private boolean isSpringSpec(SpecInfo spec) {
if (spec.isAnnotationPresent(ContextConfiguration.class)) return true;
if (contextHierarchyClass != null && spec.isAnnotationPresent(contextHierarchyClass)) return true;
return findAnnotationDescriptorForTypesMethod != null
&& ReflectionUtil.invokeMethod(
null, findAnnotationDescriptorForTypesMethod, spec.getReflection(),
new Class[] {ContextConfiguration.class, contextHierarchyClass}) != null;
}

private void checkNoSharedFieldsInjected(SpecInfo spec) {
for (FieldInfo field : spec.getAllFields()) {
if (field.getReflection().isAnnotationPresent(Shared.class)
Expand Down

0 comments on commit 718bf42

Please sign in to comment.