当前位置: 首页 > 知识库问答 >
问题:

如何从Spock测试进行CDI/SE?

慕俊语
2023-03-14

我一直在使用CDIUnit和其他各种形式的CDI/SE解决方案来实现测试(junit),这些测试可以减少模拟,并更多地使用我的应用程序堆栈(我想是集成测试)。

无论如何,我也非常喜欢Spock进行测试,我认为应该抓紧时间从CDI/SE空间和Spock中混合一些东西,以便能够制定能够访问大部分CDI内容的规范。

许多CDI的单元运行程序(CDIUnit、WeldjUnit、deltaspike、为SE做cdi或Weld的随机博客片段)都是JUnit运行程序,似乎与Spock不太匹配。经过多次修补,我已经提炼出一个非常简单的东西:用非常简单的@Inject焊接/se spock。但它不起作用。

似乎weld确实“启动”了,我的可注射体的后构造函数也启动了。但是,在Spock feature方法中,对可注入的引用为null。在进一步的测试中,我使用@InjectSetter而不是实例变量,setter似乎使用了非空引用,但在我的feature方法启动时;引用再次为空。我还把Weld和container@Shared弄得一团糟,并试图在setupSpec()生命周期方法中初始化;同样的结果。

是否可以通过Spock测试进行简单的CDI操作?

这里有一个史波克的样本,展示了我正在努力实现的目标:

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
    }
}

我有点“工作”。不确定原因或方式,甚至不确定它是否有任何好处(对于解决方案)。我想知道更多关于发生了什么以及为什么。样品:

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);
    }

}

因此,我观察/推测,真正发生的事情是斯波克创建了我的规范(“this”)的一个实例,然后在使用weld/se的设置中,我使用select()创建了另一个实例。get()调用('me')。简单的打印显示“我”!='这“实际上是注入发生在通过select()创建的托管实例上。get()。我想大概是这样。

所以我想我真正想要的是注射发生在“这个”上。一些谷歌搜索,我偶然发现了这个: CDI注入到现有的对象中,这是类似的东西。我受到DeltaSpike的injectFields的启发,并重构了WeldSpec,比如:

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()
        }
    }
}

这是可行的,我的规范更自然一些:

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
    }
}

现在来看看这是否有什么好处。。。。

共有2个答案

司马渝
2023-03-14

Update2有一个性能问题:由于setup()在每个特征方法之前运行,因此每个特征方法都会初始化Weld,并扫描类路径和所有。

我把它移动到静态-但在这种情况下没有关闭(我找不到一个地方为它关闭钩子之外,但可能它甚至不需要测试):

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()
//        }
//    }
}
相化
2023-03-14

根据更新2;我有些东西在工作。

 类似资料:
  • Spock规范如下所示: 是一个测试记录列表,对于该列表的每个成员,方法将按顺序运行。我想要的是,列表的前k个成员运行一个线程,下面的k个成员在第二个线程中运行,等等...理论上,使用Executors框架和类(因为Spock依赖于JUnit),这可以相对容易地完成。 然而,问题是如何将更小的注入到具有方法的类中,因为Spock不允许构造函数,而JUnitCore需要类名(具有测试/规范的类),而

  • 使用Spock运行集成测试(例如)的最佳方式是什么?我想引导整个Spring Boot应用程序,并执行一些HTTP调用来测试整个功能。 我可以用JUnit(首先运行应用程序,然后执行测试): 但是有了Spock,应用程序就不会启动了:

  • 我对测试有点陌生(吓人,嗯),所以如果这是无知的话,请原谅我。 根据对测试框架所做的更改,spock spring 0.7-groovy-2.0是否与新的spring 3.2版本兼容? 我已经查看了正在测试的Spring 3.2文档: 以及新闻下的斯波克文档: 但是,没有任何东西可以帮助我判断新的Spring3.2测试框架是否仍然允许以Spring3.2测试(Spring3.2文档第11.3.4节

  • 我在Spring控制器中加载数据库驱动pec.groovymethod.but我不知道如何调用Groovy脚本中的方法。有人能给我建议吗? 带着导游http://docs.groovy-lang.org/latest/html/documentation/guide-integrating.html 我只想访问http://127.0.0.1:8080/spock/test/spock然后运行数据

  • 集成测试是对已经进行单元测试的各个部分的一种整合测试。集成是昂贵的,并且它出现在测试中。你必须把这个考虑到你的预计和时间表里。 理想情况下,你应该这样组织一个项目,使得最后没有一个阶段是必须通过显式集成来进行的。这比在项目过程中,随着事情完成逐渐集成事情要好得多。如果这是不可避免的,请仔细评估。

  • 压力测试很有趣,一开始好像压测的目的是找出系统在负载下能不能工作。现实中,系统在负载下确实能工作,但在负载足够重的某些情况下不能工作。我把这叫做碰壁或撞响[1]。可能会有例外,但大多数情况下会有这么一堵“墙”。压测的目的是为了指出墙在哪里,然后弄清楚怎么把墙移得更远些。 压测计划需要在工程的早期就规划好,因为它经常有助于弄清楚到底什么是被期望的。两秒的网页请求是一个悲伤的失败还是一个了不起的成功?