How to do CDI / SE from Spock Test?

I use CDIUnit and other various forms of CDI / SE solutions to implement tests (junit) that do less mockery and use more of my application stack (integration tests I suppose).

Anyway, I also really like Spock for testing, and thought it should be tied to linking something from the CDI / SE and spock space to be able to create specs that have access to most of the CDI stuff.

Many of the runners for CDI (CDIUnit, weldjunit, deltaspike, random blog snippets that do cdi or weld for SE) are JUnit Runners and don't seem to be very good at Spock. After a lot of rework, I went overboard with a very simple thing: weld / se + spock with a really simple @Inject. But that won't work.

The weld seems to start to "fire up" and my injection message constructor fires. However, the injection formula reference is zero in the Spock function method. In the next test, I was using the @Inject setter, not an instance variable, and the setter seemed to trigger a non-null reference, but by the time my function method was run; the link is null again. I also messed up with Weld and @Shared container creation and tried to initialize the lifecycle setupSpec () method; the same results.

Can simple CDI stuff be done from Spock test?

Here's a hunk Spock example that shows what I'm trying to achieve:

package fhw

import spock.lang.Specification
import javax.inject.Inject
import org.jboss.weld.environment.se.Weld
import org.jboss.weld.environment.se.WeldContainer
import spock.lang.Shared

public class Chompers
    extends Specification
{
    def Weld weld
    def WeldContainer container

    def setup()
    {
        println this
        weld = new Weld()
        container = weld.initialize()
        container.instance().select(this.class).get()
        //container.instance().select(this.class)
    }

    @Inject
    def SomethingToTest somethingToTest;

    //@Inject
    //def setSomethingToTest(SomethingToTest sst)
    //{
    //    somethingToTest = sst
    //    println "setter fired  and somethingToTest is null?  " + (null == somethingToTest)
    //}

    def "my first Test"()
    {
        given:
            println "given I used weld wrapper spec From spock (instance " + this + ")"


        when:
            println "when I do something, in this case, like just haveing @Inject annotation"

        then:
            somethingToTest
    }
}

      

UPDATE

I have something like "working". Not sure why or how and not sure if it's even good (for a solution). I would like to know more about what is happening and why. Examples:

package fhw

import org.junit.runner.RunWith
import spock.lang.*
import org.jboss.weld.environment.se.Weld
import org.jboss.weld.environment.se.WeldContainer
import javax.enterprise.inject.Instance

class WeldSpec
    extends Specification
{

    def Weld weld
    def WeldContainer container
    def me

    def setup()
    {
        weld = new Weld()
        container = weld.initialize()
        me = container.instance().select(this.class).get()
    }

    def cleanup()
    {
        if(weld)
        {
            weld.shutdown()
        }
    }
}

      


package fhw

import spock.lang.*
import javax.inject.Inject
import fhw.spock.*

public class Bonnie
    extends WeldSpec
{
    @Inject 
    def SomethingToTest somethingToTest;

    def "my silly first cdi-spock test"()
    {        
        when:
            def s = me.somethingToTest.upShift("fred")

        then:
            "FRED" == s 
    }
}

      


package fhw;

import javax.annotation.PostConstruct;
import javax.inject.Named;


@Named
public class SomethingToTest
{
    public SomethingToTest() {}

    @PostConstruct
    private void init()
    {
        System.out.println("SomethingToTest:  post construction");
    }


    public String upShift(String in)
    {
        String s = null;
        if(null != in)
        {
            s = in.toUpperCase();
        }
        return(s);
    }

}

      


UPDATE 2

So what I noticed / assumed that what actually happened was that spock instantiated my spec ('this') and then in setup using weld / se I created another one with select () calls. get () ('me'). Plain printlns showed 'me'! = 'This', and indeed the injection happened on a managed instance created with select (). Get (). Or I think.

So, I think I really want the injection to happen on 'this'. Some googling and I came across this: CDI injection into an existing object , something similar. I became inspired by DeltaSpike injectFields and refactored WeldSpec as:

package fhw

import spock.lang.*
import javax.enterprise.inject.spi.BeanManager
import javax.enterprise.inject.spi.InjectionTarget
import org.jboss.weld.environment.se.Weld
import org.jboss.weld.environment.se.WeldContainer
import javax.enterprise.context.spi.CreationalContext
import javax.enterprise.inject.spi.AnnotatedType

class WeldSpec
    extends Specification
{
    def Weld weld
    def WeldContainer container

    def setup()
    {
        weld = new Weld()
        container = weld.initialize()
        BeanManager beanManager = container.getBeanManager()
        CreationalContext<? extends WeldSpec> creationalContext = beanManager.createCreationalContext(null)
        AnnotatedType<? extends WeldSpec> annotatedType = beanManager.createAnnotatedType((Class<? extends WeldSpec>) this.getClass())
        InjectionTarget<? extends WeldSpec> injectionTarget = beanManager.createInjectionTarget(annotatedType)
        injectionTarget.inject(this, creationalContext);            
    }

    def cleanup()
    {
        if(weld)
        {
            weld.shutdown()
        }
    }
}

      


This works, and my spec is somewhat more natural:

package fhw

import spock.lang.*
import javax.inject.Inject
import fhw.spock.*

public class Bonnie
    extends WeldSpec
{
    @Inject 
    def SomethingToTest somethingToTest;

    def "my silly first cdi-spock test"()
    {        
        when:
            def s = somethingToTest.upShift("fred")

        then:
            "FRED" == s
    }
}

      


Now to see if this is good for anything ....

+3


source to share


2 answers


as of update 2; Something works for me.



0


source


Update2 has a performance issue: because setup () is run before each method, Weld is initialized for every method on the objects - with the scan classpath and all.

I moved it to static - but there is no shutdown in this case (I couldn't find a place for it outside of the outriggers, but it probably isn't even needed for tests):



class CdiSpecification extends Specification {

    private static Weld weld
    private static WeldContainer container
    private static BeanManager beanManager

    static {
        weld = new Weld()
        container = weld.initialize()
        beanManager = container.getBeanManager()
    }

    def setup() {
        CreationalContext<? extends CdiSpecification> creationalContext = beanManager.createCreationalContext(null)
        AnnotatedType<? extends CdiSpecification> annotatedType = beanManager.createAnnotatedType((Class<? extends CdiSpecification>) this.getClass())
        InjectionTarget<? extends CdiSpecification> injectionTarget = beanManager.createInjectionTarget(annotatedType)
        injectionTarget.inject(this, creationalContext);
    }

//    def cleanup() {
//        if (weld) {
//            weld.shutdown()
//        }
//    }
}

      

0


source







All Articles