Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Spock 1.2 Spring Integration Test annotations SpringBean, SpringSpy, UnwrapAopProxy
//Just a snippet to show how to include Spock 1.2 before it has been released
repositories {
maven {
//Required until Spock 1.2 is released out of snapshot
url 'https://oss.sonatype.org/content/repositories/snapshots/'
}
}
dependencies {
testCompile("org.springframework.boot:spring-boot-starter-test") //for AopTestUtils
testCompile("org.spockframework:spock-core:1.2-groovy-2.4-SNAPSHOT")
testCompile("org.spockframework:spock-spring:1.2-groovy-2.4-SNAPSHOT")
}
import org.springframework.test.util.AopTestUtils
/** Showing how to unwrap the AOP proxy manually to reuse the cached Spring context config */
@Import([IntegrationTestMockingConfig])
class PersonControllerIntProxiedTest extends Specification {
@Autowired MockMvc mvc
/** A simple mock can just be autowired */
@Autowired ExternalRankingService externalRankingServiceMock
/** A Proxied mock must first be AOP unwrapped */
@Autowired ValidatedExternalRankingService proxiedValidatedExternalRankingService
ValidatedExternalRankingService validatedExternalRankingService
void setup() {
//Manually unwrap the AOP proxy
validatedExternalRankingService = AopTestUtils.getUltimateTargetObject(proxiedValidatedExternalRankingService)
}
def "GetValidatedRank"() { /*Test goes here...*/ }
}
@SpringBootTest
@AutoConfigureMockMvc
class PersonControllerIntSpock12ProxiedSpec extends Specification {
@Autowired MockMvc mvc
/**
* SpringSpy will wrap the Spring injected Service with a Spy
* UnwrapAopProxy will remove the cglib @Validated proxy
*/
@SpringSpy
@UnwrapAopProxy
ValidatedExternalRankingService validatedExternalRankingService
def "GetValidatedRank"() {
when: 'Calling getRank for a known seed data entity'
MvcResult mvcResult = mvc.perform(get("/persons/1/validatedRank").contentType(APPLICATION_JSON))
.andExpect(status().is2xxSuccessful()).andReturn()
then: 'we define the mock for the external service'
1 * validatedExternalRankingService.getRank(_) >> {
new Rank(level: 1, classification: 'Captain')
}
noExceptionThrown()
when: 'inspecting the contents'
def resultingJson = mvcResult.response.contentAsString
then: 'the result contains a mix of mocked service data and actual wired component data'
resultingJson == 'Capt James Kirk ~ Captain:Level 1'
}
}
@SpringBootTest
@AutoConfigureMockMvc
class PersonControllerIntSpock12Spec extends Specification {
@Autowired MockMvc mvc
/** SpringBean will put the mock into the spring context */
@SpringBean
ExternalRankingService externalRankingService = Mock()
def "GetRank"() {
when: 'Calling getRank for a known seed data entity'
MvcResult mvcResult = mvc.perform(get("/persons/1/rank").contentType(APPLICATION_JSON))
.andExpect(status().is2xxSuccessful()).andReturn()
then: 'we define the mock for JUST the external service'
1 * externalRankingService.getRank(_) >> {
new Rank(level: 1, classification: 'Captain')
}
noExceptionThrown()
when: 'inspecting the contents'
def resultingJson = mvcResult.response.contentAsString
then: 'the result contains a mix of mocked service data and actual wired component data'
resultingJson == 'Capt James Kirk ~ Captain:Level 1'
}
}
//An example error seen when trying to Spy a Spring Proxied object, but forgetting to unwrap it first
// Notice the lowercase/uppercase 'v' in validatedExternalRankingService that somewhat points to
// the mock being a slightly different object.
Too few invocations for:
1 * validatedExternalRankingService.getRank(_) >> {
new Rank(level: 1, classification: 'Captain')
} (0 invocations)
Unmatched invocations (ordered by similarity):
1 * ValidatedExternalRankingService.getRank(com.objectpartners.eskens.entities.Person(1, James, Kirk, Capt))
/** This class is @Validated, which makes it a Spring AOP proxied service */
@Service
@Validated
class ValidatedExternalRankingService {
Rank getRank(Person person) { throw new RuntimeException('This feature is not yet implemented.') }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.