spock icon indicating copy to clipboard operation
spock copied to clipboard

Spock + Spring boot + start execution of spock from Java class

Open sadaphalpramod opened this issue 5 years ago • 9 comments

I am trying to run Spock classes from Java class using Junit runner class and able to run it. But after that beans are not autowiring. To use every bean i need to use ApplicationContextAware and get beans.

sadaphalpramod avatar Apr 05 '19 17:04 sadaphalpramod

That approach is quite uncommon. Could you paste minimal code that shows the problem and also explain why you need to do it that way?

szpak avatar Apr 05 '19 17:04 szpak

I have created spring boot application. After starting spring boot app i am executing api exposed in it. In that api (rest controller) there is logic to invoke Spock tests(using Junit runner). I am able to run Spock specs from there successfully.

@GetMapping(value = "/testurl", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity init() throws IOException {
        FileUtils.cleanDirectory(new File("src/main/resources/templates/"));
        JUnitCore.runClasses(SpockTestSampleSpec.class, SpockTestSample2Spec.class);

        return new ResponseEntity(HttpStatus.OK);
}

Below is Spec class

class SpockTestSampleSpec extends Specification {

    def "Test Case 1"() {
	@Autowired
	AutomationTestUtils automationTestUtils		
        
	setup: "setup"
        def request = automationTestUtils.getRequestData()
        println("In test case 1")

        when: "execute request"
        def response = get(request, REQUEST_DATA_URL, true, true)

        then: "verify response"
        println("Test Case1 completed")
        verifyResponse(response)
    }

In above code automationTestUtils is getting as null. And it is declared as,

@Component
public class AutomationTestUtils {
.

When I execute SpockTest directly(SpockTestSampleSpec using mvn command or by 'Run Test' option on groovy in intelliJ) then automationTestUtils is not null. It is null when executed using JUnitCore.runClasses(SpockTestSampleSpec.class, SpockTestSample2Spec.class);

I need it in this way because the application is residing in server where i can not execute mvn commands.

sadaphalpramod avatar Apr 08 '19 16:04 sadaphalpramod

A quick shot, without going deep into your approach is to move the:

	@Autowired
	AutomationTestUtils automationTestUtils		

definition from a method to the class (specification) level. Spring beans cannot be injected into local variables in methods (in both Spock and JUnit).

szpak avatar Apr 08 '19 21:04 szpak

You may also want sth like @ContextConfiguration(locations = ["classpath:/spring-context.xml"]) on your spec to point to the context config file

rtretyak avatar Apr 09 '19 08:04 rtretyak

sorry that was typo . I placed automatonTestUtils outside method like,

class SpockTestSampleSpec extends Specification {
	@Autowired
	AutomationTestUtils automationTestUtils		

    def "Test Case 1"() {       
	setup: "setup"
        def request = automationTestUtils.getRequestData()
        println("In test

But it is not working. I also tried @ContextConfiguration(locations = ["classpath:/spring-context.xml"]) , it is also not working.

sadaphalpramod avatar Apr 09 '19 10:04 sadaphalpramod

This works fine for me: spec:

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification

@ContextConfiguration(locations = ["classpath:/spring-context-example.xml"])
class MySpec extends Specification {
    @Autowired
    MyService myService

    def "a test"() {
        expect:
        myService != null
        println myService.foo()
    }
}

component:

import org.springframework.stereotype.Component

@Component
class MyService {
    def foo() {
        return "foo"
    }
}

config:

<?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"
       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">
    <context:component-scan base-package="package.where.myservice.is.located"/>
</beans>

rtretyak avatar Apr 09 '19 11:04 rtretyak

XML? I hope you are not bound to Spring 3. @ComponentScan('your-package') should do the same.

Anyway, is running the Spock test in a production context (at least in the acceptance tests) only dictated by a need to generate fancy report or you have also some other reasons?

szpak avatar Apr 09 '19 16:04 szpak

spocktestautomation.zip

I have added sample project. In which after executing SpockTestSampleSpec I am getting NullPointerException.

java.lang.NullPointerException: Cannot invoke method getRequest() on null object
	at com.test.automation.test.SpockTestSampleSpec.Test Case 1(SpockTestSampleSpec.groovy:19)

sadaphalpramod avatar Apr 10 '19 07:04 sadaphalpramod

spocktestautomation.zip

I have altered your project in such a way that the test does succeed.

The main changes are:

  • extra dependancy (spock-spring)
  • included a spring boot application (not sure why this is needed, but it does not run properly without it)
  • included @SprintBootTest

I hope this helps.

BoukeNijhuis avatar Apr 30 '19 19:04 BoukeNijhuis