spockframework / spock

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

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

Open sadaphalpramod opened 5 years ago

sadaphalpramod commented 5 years ago

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.

szpak commented 5 years ago

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?

sadaphalpramod commented 5 years ago

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.

szpak commented 5 years ago

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).

rtretyak commented 5 years ago

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

sadaphalpramod commented 5 years ago

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.

rtretyak commented 5 years ago

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>
szpak commented 5 years ago

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?

sadaphalpramod commented 5 years ago

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)
BoukeNijhuis commented 5 years ago

spocktestautomation.zip

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

The main changes are:

I hope this helps.