spockframework / spock

The Enterprise-ready testing and specification framework.
https://spockframework.org
Apache License 2.0
3.54k stars 466 forks source link

Use of @SpringBean and Spring Feign with SpEL removes ConfigurationPropertiesBindingPostProcessor from Spring's context #1144

Open silovmar opened 4 years ago

silovmar commented 4 years ago

Issue description

When the annotation @SpringBean with Spring Cloud OpenFeign and SpEL is used then Spock refreshes Spring context and ConfigurationPropertiesBindingPostProcessor is not registered (also some other BeanPostProcessors are not registered as well), so, in my case, a value from the property test of ApplicationProperties.java is NOT replaced with a value of a propertyapplication.test from application-test.properties.

When the annotation @SpringBean is not used then the context is loaded with the post processor.

How to reproduce

ApplicationProperties.java

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "application")
public class ApplicationProperties {
    private boolean test = true;
    private String url;
}

application-test.properties

application.test=false
application.url=localhost:7080

AnotherAppRestClient.java

@FeignClient(name = "another-app", url = "#{applicationProperties.url}")
public interface AnotherAppRestClient {...}

ApplicationSpec.groovy

import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import spock.lang.Specification

@SpringBootTest
class LotteryApplicationSpec extends Specification {

    @Autowired
    private ApplicationProperties applicationProperties

    @SpringBean
    MyService myService = Mock()

    def "Application context is properly created"() {
        expect:
        applicationProperties.test == false
    }
}

When the anntation @SpringBean with the service is commented then the test passes.

It also works when I rewrite the Feign client with value replacement instead of SpEL for url parameter of the FeignClient annotation:

@FeignClient(name = "another-app", url = "${application.url}")
public interface AnotherAppRestClient {...}

Workaround

Use ${application.url} instead of #{applicationProperties.url}

Additional Environment information

Java/JDK

java -version

openjdk 11.0.2 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)

Groovy version

groovy -version Groovy Version: 2.5.8 JVM: 11.0.2 Vendor: Oracle Corporation OS: Mac OS X

Build tool version

Gradle

gradle -version

 ------------------------------------------------------------
 Gradle 6.3
 ------------------------------------------------------------

Build time:   2020-03-24 19:52:07 UTC
Revision:     bacd40b727b0130eeac8855ae3f9fd9a0b207c60

Kotlin:       1.3.70
Groovy:       2.5.10
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          11.0.2 (Oracle Corporation 11.0.2+9)
OS:           Mac OS X 10.15.4 x86_64

Operating System

Mac

IDE

IntelliJ

Build-tool dependencies used

Gradle/Grails

annotationProcessor("org.springframework.boot:spring-boot-configuration-processor") // Spring Boot 2.2.4.RELEASE

implementation("org.springframework.cloud:spring-cloud-starter-openfeign") // version Hoxton.SR1

testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.spockframework:spock-core:2.0-M2-groovy-2.5")
testImplementation("org.spockframework:spock-spring:2.0-M2-groovy-2.5")
leonard84 commented 4 years ago

Can you provide an SSCCE? And does this only happen with feign or have you noticed it with other things too? Does this also happen with springs own @MockBean? Spocks implementation is based on that implementation.